diff --git a/bundles/core/src/main/java/com/adobe/cq/wcm/core/components/internal/LazyValue.java b/bundles/core/src/main/java/com/adobe/cq/wcm/core/components/internal/LazyValue.java new file mode 100644 index 0000000000..f4be7bb880 --- /dev/null +++ b/bundles/core/src/main/java/com/adobe/cq/wcm/core/components/internal/LazyValue.java @@ -0,0 +1,68 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ Copyright 2023 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.wcm.core.components.internal; + +import java.util.Optional; +import java.util.function.Supplier; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + + +/** + * Resolve a value lazily. + * + * In SlingModels, not all values computed in the @PostConstruct method are always + * used. That means that there might be values which are only consumed in certain + * circumstances, but which have overhead to calculate. In case this value is not used + * at all, this overhead is wasted time. + * + * Wrapping them into the LazyValue type will do the calculation of the value only + * when required. + * + * + * + * @param the type of the value + */ + +public class LazyValue { + + private Optional value; + private Supplier supplier; + + /** + * + * @param supplier to provide the value + */ + public LazyValue(@NotNull Supplier supplier) { + if (supplier == null) { + throw new IllegalArgumentException("supplier must not be null"); + } + this.supplier = supplier; + } + + @Nullable + public T get() { + if (value == null) { + value = Optional.ofNullable(supplier.get()); + } + return value.orElse(null); + } + + + + +} diff --git a/bundles/core/src/main/java/com/adobe/cq/wcm/core/components/internal/models/v1/PageImpl.java b/bundles/core/src/main/java/com/adobe/cq/wcm/core/components/internal/models/v1/PageImpl.java index aa39141cea..42ba004eeb 100644 --- a/bundles/core/src/main/java/com/adobe/cq/wcm/core/components/internal/models/v1/PageImpl.java +++ b/bundles/core/src/main/java/com/adobe/cq/wcm/core/components/internal/models/v1/PageImpl.java @@ -50,6 +50,7 @@ import com.adobe.cq.export.json.ContainerExporter; import com.adobe.cq.export.json.ExporterConstants; import com.adobe.cq.export.json.SlingModelFilter; +import com.adobe.cq.wcm.core.components.internal.LazyValue; import com.adobe.cq.wcm.core.components.internal.Utils; import com.adobe.cq.wcm.core.components.commons.link.LinkManager; import com.adobe.cq.wcm.core.components.models.Page; @@ -99,16 +100,16 @@ public class PageImpl extends AbstractComponentImpl implements Page { @Self protected LinkManager linkManager; - protected String[] keywords = new String[0]; + protected LazyValue keywords; protected String designPath; protected String staticDesignPath; protected String title; protected String description; - protected String brandSlug; + protected LazyValue brandSlug; protected String[] clientLibCategories = new String[0]; protected Calendar lastModifiedDate; - protected String templateName; + protected LazyValue templateName; protected static final String DEFAULT_TEMPLATE_EDITOR_CLIENTLIB = "wcm.foundation.components.parsys.allowedcomponents"; protected static final String PN_CLIENTLIBS = "clientlibs"; @@ -129,27 +130,34 @@ protected void initModel() { if (StringUtils.isBlank(title)) { title = currentPage.getName(); } - Tag[] tags = currentPage.getTags(); - keywords = new String[tags.length]; - int index = 0; - for (Tag tag : tags) { - keywords[index++] = tag.getTitle(currentPage.getLanguage(false)); - } + keywords = new LazyValue<>(() -> buildKeywords()); if (currentDesign != null) { String designPath = currentDesign.getPath(); if (!Designer.DEFAULT_DESIGN_PATH.equals(designPath)) { this.designPath = designPath; - if (resolver.getResource(designPath + "/static.css") != null) { + final Resource designResource = resolver.getResource(designPath); + if (designResource != null && designResource.getChild("static.css") != null) { staticDesignPath = designPath + "/static.css"; } - loadFavicons(designPath); + loadFavicons(designResource); } } populateClientlibCategories(); - templateName = extractTemplateName(); - brandSlug = Utils.getInheritedValue(currentPage, PN_BRANDSLUG); + templateName = new LazyValue<>(() -> extractTemplateName()); + brandSlug = new LazyValue<>(() -> Utils.getInheritedValue(currentPage, PN_BRANDSLUG)); } + private String[] buildKeywords() { + Tag[] tags = currentPage.getTags(); + String[] keywords = new String[tags.length]; + int index = 0; + Locale language= currentPage.getLanguage(false); + for (Tag tag : tags) { + keywords[index++] = tag.getTitle(language); + } + return keywords; + } + protected String extractTemplateName() { String templateName = null; String templatePath = pageProperties.get(NameConstants.PN_TEMPLATE, String.class); @@ -179,7 +187,12 @@ public Calendar getLastModifiedDate() { @Override @JsonIgnore public String[] getKeywords() { - return Arrays.copyOf(keywords, keywords.length); + String[] kw = keywords.get(); + if (kw != null) { + return Arrays.copyOf(kw, kw.length); + } else { + return new String[0]; + } } @Override @@ -211,12 +224,12 @@ public String getDescription() { @Override public String getBrandSlug() { - return brandSlug; + return brandSlug.get(); } @Override public String getTemplateName() { - return templateName; + return templateName.get(); } @Override @@ -290,21 +303,20 @@ private Map getChildModels(@NotNull SlingHttpServletRequest sling return itemWrappers; } - protected void loadFavicons(String designPath) { - favicons.put(PN_FAVICON_ICO, getFaviconPath(designPath, FN_FAVICON_ICO)); - favicons.put(PN_FAVICON_PNG, getFaviconPath(designPath, FN_FAVICON_PNG)); - favicons.put(PN_TOUCH_ICON_120, getFaviconPath(designPath, FN_TOUCH_ICON_120)); - favicons.put(PN_TOUCH_ICON_152, getFaviconPath(designPath, FN_TOUCH_ICON_152)); - favicons.put(PN_TOUCH_ICON_60, getFaviconPath(designPath, FN_TOUCH_ICON_60)); - favicons.put(PN_TOUCH_ICON_76, getFaviconPath(designPath, FN_TOUCH_ICON_76)); + protected void loadFavicons(@Nullable Resource designResource) { + favicons.put(PN_FAVICON_ICO, getFaviconPath(designResource, FN_FAVICON_ICO)); + favicons.put(PN_FAVICON_PNG, getFaviconPath(designResource, FN_FAVICON_PNG)); + favicons.put(PN_TOUCH_ICON_120, getFaviconPath(designResource, FN_TOUCH_ICON_120)); + favicons.put(PN_TOUCH_ICON_152, getFaviconPath(designResource, FN_TOUCH_ICON_152)); + favicons.put(PN_TOUCH_ICON_60, getFaviconPath(designResource, FN_TOUCH_ICON_60)); + favicons.put(PN_TOUCH_ICON_76, getFaviconPath(designResource, FN_TOUCH_ICON_76)); } - protected String getFaviconPath(String designPath, String faviconName) { - String path = designPath + "/" + faviconName; - if (resolver.getResource(path) == null) { - return null; - } - return path; + protected String getFaviconPath(@Nullable Resource designResource, String faviconName) { + if (designResource != null && designResource.getChild(faviconName) != null) { + return designResource.getPath() + "/" + faviconName; + } + return null; } protected void populateClientlibCategories() { @@ -344,7 +356,7 @@ protected final PageData getComponentData() { Optional.ofNullable(pageProperties.get(JcrConstants.JCR_CREATED, Calendar.class)) .map(Calendar::getTime) .orElse(null))) - .withTags(() -> Arrays.copyOf(this.keywords, this.keywords.length)) + .withTags(() -> getKeywords()) .withDescription(() -> this.pageProperties.get(NameConstants.PN_DESCRIPTION, String.class)) .withTemplatePath(() -> Optional.ofNullable(this.currentPage.getTemplate()) .map(Template::getPath) diff --git a/bundles/core/src/main/java/com/adobe/cq/wcm/core/components/internal/models/v2/PageImpl.java b/bundles/core/src/main/java/com/adobe/cq/wcm/core/components/internal/models/v2/PageImpl.java index 7d2aba79a0..0661d1161e 100644 --- a/bundles/core/src/main/java/com/adobe/cq/wcm/core/components/internal/models/v2/PageImpl.java +++ b/bundles/core/src/main/java/com/adobe/cq/wcm/core/components/internal/models/v2/PageImpl.java @@ -53,6 +53,7 @@ import com.adobe.cq.wcm.core.components.config.HtmlPageItemConfig; import com.adobe.cq.wcm.core.components.config.HtmlPageItemsConfig; import com.adobe.cq.wcm.core.components.commons.link.LinkManager; +import com.adobe.cq.wcm.core.components.internal.LazyValue; import com.adobe.cq.wcm.core.components.internal.models.v1.RedirectItemImpl; import com.adobe.cq.wcm.core.components.models.HtmlPageItem; import com.adobe.cq.wcm.core.components.models.NavigationItem; @@ -157,7 +158,7 @@ public class PageImpl extends com.adobe.cq.wcm.core.components.internal.models.v * The proxy path of the first client library listed in the style under the * "{@value Page#PN_APP_RESOURCES_CLIENTLIB}" property. */ - private String appResourcesPath; + private LazyValue appResourcesPath; /** * The redirect target as a NavigationItem. @@ -182,14 +183,14 @@ public class PageImpl extends com.adobe.cq.wcm.core.components.internal.models.v @PostConstruct protected void initModel() { super.initModel(); - this.appResourcesPath = Optional.ofNullable(currentStyle) + this.appResourcesPath = new LazyValue<>(() -> Optional.ofNullable(currentStyle) .map(style -> style.get(PN_APP_RESOURCES_CLIENTLIB, String.class)) .map(resourcesClientLibrary -> htmlLibraryManager.getLibraries(new String[]{resourcesClientLibrary}, LibraryType.CSS, true, false)) .map(Collection::stream) .orElse(Stream.empty()) .findFirst() .map(this::getProxyPath) - .orElse(null); + .orElse(null)); } protected NavigationItem newRedirectItem(@NotNull String redirectTarget, @NotNull SlingHttpServletRequest request, @NotNull LinkManager linkManager) { @@ -216,7 +217,7 @@ private String getProxyPath(ClientLibrary lib) { } @Override - protected void loadFavicons(String designPath) { + protected void loadFavicons(Resource designPath) { } @Override @@ -255,7 +256,7 @@ public String[] getClientLibCategoriesJsHead() { @Override public String getAppResourcesPath() { - return appResourcesPath; + return appResourcesPath.get(); } @Override diff --git a/content/src/content/jcr_root/apps/core/wcm/components/form/container/v1/container/_cq_design_dialog/.content.xml b/content/src/content/jcr_root/apps/core/wcm/components/form/container/v1/container/_cq_design_dialog/.content.xml index 37c056b636..23cd6322c8 100644 --- a/content/src/content/jcr_root/apps/core/wcm/components/form/container/v1/container/_cq_design_dialog/.content.xml +++ b/content/src/content/jcr_root/apps/core/wcm/components/form/container/v1/container/_cq_design_dialog/.content.xml @@ -56,7 +56,6 @@ @@ -47,8 +46,7 @@ typeHint="Long" required="{Boolean}true" min="{Long}0" - max="{Long}100" - defaultValue="{Long}82" /> + max="{Long}100"/> @@ -152,8 +151,7 @@ typeHint="Long" required="{Boolean}true" min="{Long}0" - max="{Long}100" - defaultValue="{Long}82" /> + max="{Long}100"/> diff --git a/content/src/content/jcr_root/apps/core/wcm/components/image/v3/image/_cq_design_dialog/.content.xml b/content/src/content/jcr_root/apps/core/wcm/components/image/v3/image/_cq_design_dialog/.content.xml index 106a4ddaa2..6d1a2e9fd3 100644 --- a/content/src/content/jcr_root/apps/core/wcm/components/image/v3/image/_cq_design_dialog/.content.xml +++ b/content/src/content/jcr_root/apps/core/wcm/components/image/v3/image/_cq_design_dialog/.content.xml @@ -119,7 +119,6 @@ name="./resizeWidth" typeHint="Long" required="{Boolean}false" - defaultValue="{Long}1280" min="{Long}1" max="{Long}3840"/> @@ -170,8 +168,7 @@ typeHint="Long" required="{Boolean}false" min="{Long}0" - max="{Long}100" - defaultValue="{Long}82" /> + max="{Long}100" />