From 565b9213fd1d3a63f2402dcdff8eb5e0312b6c99 Mon Sep 17 00:00:00 2001 From: Harwinder Singh Date: Fri, 8 Sep 2023 16:03:59 -0400 Subject: [PATCH 1/6] Feature/mcptools/bulk page tag creator (#3171) * MCP Tool : AEM Bulk Pages Tagger --------- Co-authored-by: david g --- CHANGELOG.md | 3 + .../mcp/impl/processes/BulkPageTagger.java | 254 ++++++++++++++++++ .../impl/processes/BulkPageTaggerFactory.java | 39 +++ .../impl/processes/BulkPageTaggerTest.java | 90 +++++++ .../mcp/impl/processes/bulkPageTagger.xlsx | Bin 0 -> 9907 bytes 5 files changed, 386 insertions(+) create mode 100644 bundle/src/main/java/com/adobe/acs/commons/mcp/impl/processes/BulkPageTagger.java create mode 100644 bundle/src/main/java/com/adobe/acs/commons/mcp/impl/processes/BulkPageTaggerFactory.java create mode 100644 bundle/src/test/java/com/adobe/acs/commons/mcp/impl/processes/BulkPageTaggerTest.java create mode 100644 bundle/src/test/resources/com/adobe/acs/commons/mcp/impl/processes/bulkPageTagger.xlsx diff --git a/CHANGELOG.md b/CHANGELOG.md index 785f222695..c1e1d247f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com) ## Unreleased ([details][unreleased changes details]) +#3170 - Added a new MCP tool to bulk tag AEM content pages via an Excel file input. + + ## Fixed - #3040 - Fixed bug where namespaced multi-fields would have the namespace 2 times diff --git a/bundle/src/main/java/com/adobe/acs/commons/mcp/impl/processes/BulkPageTagger.java b/bundle/src/main/java/com/adobe/acs/commons/mcp/impl/processes/BulkPageTagger.java new file mode 100644 index 0000000000..e92f23dc46 --- /dev/null +++ b/bundle/src/main/java/com/adobe/acs/commons/mcp/impl/processes/BulkPageTagger.java @@ -0,0 +1,254 @@ +/*- + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2013 - 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. + * #L% + */ +package com.adobe.acs.commons.mcp.impl.processes; + +import com.adobe.acs.commons.fam.ActionManager; +import com.adobe.acs.commons.mcp.ProcessDefinition; +import com.adobe.acs.commons.mcp.ProcessInstance; +import com.adobe.acs.commons.mcp.form.FileUploadComponent; +import com.adobe.acs.commons.mcp.form.FormField; +import com.adobe.acs.commons.mcp.model.GenericBlobReport; +import com.adobe.acs.commons.mcp.util.StringUtil; +import com.day.cq.tagging.Tag; +import com.day.cq.wcm.api.Page; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.apache.sling.api.resource.ResourceResolver; +import org.apache.sling.api.resource.Resource; +import org.apache.sling.api.resource.LoginException; +import org.apache.sling.api.resource.ModifiableValueMap; +import org.apache.sling.api.resource.PersistenceException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jcr.RepositoryException; +import java.io.InputStream; +import java.io.Serializable; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Iterator; +import java.util.HashSet; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * The type Bulk page tagger. + */ +public class BulkPageTagger extends ProcessDefinition implements Serializable { + private static final Logger log = LoggerFactory.getLogger(BulkPageTagger.class); + private static final long serialVersionUID = 798823856839772874L; + + /** + * The constant NAME. + */ + public static final String NAME = "Bulk Page Tagger"; + + /** + * The Excel file. + */ + @FormField( + name = "Excel File", + description = "Provide the .xlsx file that defines the content pages and the corresponding cq:tags to be added on the pages", + component = FileUploadComponent.class, + options = {"mimeTypes=application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "required"} + ) + public transient InputStream excelFile = null; + + + @Override + public void init() throws RepositoryException { + // Nothing to be done here. + + } + + + @Override + public void buildProcess(ProcessInstance instance, ResourceResolver rr) throws LoginException { + report.setName(instance.getName()); + instance.getInfo().setDescription("Bulk Tag AEM content Pages"); + instance.defineCriticalAction("Parse Excel File", rr, this::parseExcel); + instance.defineCriticalAction("Add Tags to Content Pages", rr, this::tagPages); + + } + + + /** + * The Page tag mapping dataStructure. + */ + transient volatile HashMap pageTagMapping = new LinkedHashMap<>(); + + /** + * Parse input excel. + * + * @param manager the manager + * @throws Exception the exception + */ + @SuppressWarnings("squid:S112") + public void parseExcel(ActionManager manager) throws Exception { + manager.withResolver(rr -> { + final XSSFWorkbook workbook = new XSSFWorkbook(excelFile); + final XSSFSheet sheet = workbook.getSheetAt(0); + + final Iterator rows = sheet.rowIterator(); + final String tagsRootPath = new TagCreator.TagRootResolver(rr).getTagsLocationPath(); + + + if (tagsRootPath == null) { + recordAction(ReportRowSatus.FAILED_TO_PARSE, + "Abandoning Tag parsing. Unable to determine AEM Tags root (/content/cq:tags vs /etc/tags). Please ensure the path exists and is accessible by the user running Tag Creator.", "N/A"); + return; + } + + while (rows.hasNext()) { + final Row row = rows.next(); + if (row.getCell(0) == null) { + break; + } + if (row.getRowNum() != 0 && row.getCell(0) != null) { + pageTagMapping.put(row.getCell(0).getStringCellValue(), row.getCell(1).getStringCellValue()); + } + } + + }); + + } + + + /** + * Tag pages from the excel file with cq:tags. + * + * @param manager the manager + * @throws Exception the exception + */ + @SuppressWarnings("squid:S112") + public void tagPages(ActionManager manager) throws Exception { + + manager.withResolver(rr -> { + + pageTagMapping.forEach((key, value) -> { + BulkPageTagger.ReportRowSatus status; + Resource resource = rr.getResource(key); + if (resource != null) { + Page page = resource.adaptTo(Page.class); + if (page != null) { + Tag[] existingPageTags = page.getTags(); + String[] tagIds = Stream.of(existingPageTags) + .map(Tag::getTagID) + .toArray(String[]::new); + Set updatedTags = Arrays.stream(value.split("[;\n]")) + .map(String::trim) + .collect(Collectors.toSet()); + updatedTags.addAll(Arrays.asList(tagIds)); + String[] updatedTagsArray = updatedTags.stream().toArray(String[]::new); + + ModifiableValueMap properties = page.getContentResource().adaptTo(ModifiableValueMap.class); + properties.put(com.day.cq.tagging.TagConstants.PN_TAGS, updatedTagsArray); + try { + rr.commit(); + status = ReportRowSatus.UPDATED_EXISTING; + recordAction(status, page.getPath(), Arrays.toString(updatedTagsArray)); + } catch (PersistenceException e) { + status = ReportRowSatus.FAILED_TO_UPDATE; + recordAction(status, page.getPath(), Arrays.toString(updatedTagsArray)); + log.error(String.format("Unable to add tags to page with page path - %s ", page.getPath())); + } + + + } + + } + + }); + }); + } + + + /** + * Reporting + **/ + + + private final transient GenericBlobReport report = new GenericBlobReport(); + + private final transient ArrayList> reportRows = new ArrayList<>(); + + private enum ReportColumns { + /** + * Status report columns. + */ + STATUS, + /** + * Page path report columns. + */ + PAGE_PATH, + /** + * Tags array report columns. + */ + TAGS_ARRAY + } + + /** + * The enum Report row satus. + */ + public enum ReportRowSatus { + /** + * Created report row satus. + */ + CREATED, + /** + * Updated existing report row satus. + */ + UPDATED_EXISTING, + /** + * Failed to parse report row satus. + */ + FAILED_TO_PARSE, + /** + * Failed to update report row satus. + */ + FAILED_TO_UPDATE + } + + + private void recordAction(BulkPageTagger.ReportRowSatus status, String pagePath, String tags) { + final EnumMap row = new EnumMap<>(BulkPageTagger.ReportColumns.class); + + row.put(BulkPageTagger.ReportColumns.STATUS, StringUtil.getFriendlyName(status.name())); + row.put(ReportColumns.PAGE_PATH, pagePath); + row.put(ReportColumns.TAGS_ARRAY, tags); + + reportRows.add(row); + } + + + @Override + public void storeReport(ProcessInstance instance, ResourceResolver rr) throws RepositoryException, PersistenceException { + report.setRows(reportRows, BulkPageTagger.ReportColumns.class); + report.persist(rr, instance.getPath() + "/jcr:content/report"); + } + + +} diff --git a/bundle/src/main/java/com/adobe/acs/commons/mcp/impl/processes/BulkPageTaggerFactory.java b/bundle/src/main/java/com/adobe/acs/commons/mcp/impl/processes/BulkPageTaggerFactory.java new file mode 100644 index 0000000000..0c9ba7c79d --- /dev/null +++ b/bundle/src/main/java/com/adobe/acs/commons/mcp/impl/processes/BulkPageTaggerFactory.java @@ -0,0 +1,39 @@ +/*- + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2013 - 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. + * #L% + */ +package com.adobe.acs.commons.mcp.impl.processes; + +import com.adobe.acs.commons.mcp.ProcessDefinitionFactory; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Service; + +@Component +@Service(ProcessDefinitionFactory.class) +public class BulkPageTaggerFactory extends ProcessDefinitionFactory { + + @Override + public String getName() { + return BulkPageTagger.NAME; + } + + @Override + protected BulkPageTagger createProcessDefinitionInstance() { + return new BulkPageTagger(); + } +} diff --git a/bundle/src/test/java/com/adobe/acs/commons/mcp/impl/processes/BulkPageTaggerTest.java b/bundle/src/test/java/com/adobe/acs/commons/mcp/impl/processes/BulkPageTaggerTest.java new file mode 100644 index 0000000000..3e08035a41 --- /dev/null +++ b/bundle/src/test/java/com/adobe/acs/commons/mcp/impl/processes/BulkPageTaggerTest.java @@ -0,0 +1,90 @@ +/*- + * #%L + * ACS AEM Commons Bundle + * %% + * Copyright (C) 2013 - 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. + * #L% + */ +package com.adobe.acs.commons.mcp.impl.processes; + +import com.adobe.acs.commons.fam.ActionManager; +import com.adobe.acs.commons.functions.CheckedConsumer; +import io.wcm.testing.mock.aem.junit.AemContext; +import org.apache.jackrabbit.JcrConstants; +import org.apache.sling.api.resource.ResourceResolver; +import org.apache.sling.testing.mock.sling.ResourceResolverType; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.stubbing.Answer; + + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.*; + +@RunWith(MockitoJUnitRunner.class) +public class BulkPageTaggerTest { + + @Rule + public final AemContext context = new AemContext(ResourceResolverType.JCR_MOCK); + + private BulkPageTagger bulkPageTagger; + + @Mock + private ActionManager actionManager; + + @Before + public void setUp() throws Exception { + bulkPageTagger = new BulkPageTagger(); + bulkPageTagger.excelFile = getClass().getResourceAsStream("/com/adobe/acs/commons/mcp/impl/processes/bulkPageTagger.xlsx"); + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + CheckedConsumer method = (CheckedConsumer) invocation.getArguments()[0]; + method.accept(context.resourceResolver()); + return null; + } + }).when(actionManager).withResolver(any(CheckedConsumer.class)); + + } + + @Test + public void testParseExcel() throws Exception { + + final String tagsRootPath = com.day.cq.tagging.TagConstants.TAG_ROOT_PATH; + context.create().resource(tagsRootPath, JcrConstants.JCR_PRIMARYTYPE, "sling:Folder"); + context.resourceResolver().commit(); + bulkPageTagger.parseExcel(actionManager); + + final int expected = 9; + assertEquals(expected,bulkPageTagger.pageTagMapping.size() ); + } + + @Test + public void testTagPages() throws Exception { + + bulkPageTagger.parseExcel(actionManager); + context.create().page("/content/wknd/language-masters/en/about-us"); + context.create().resource("/content/wknd/language-masters/en/about-us/jcr:content", + JcrConstants.JCR_PRIMARYTYPE, + "cq:pagecontent","cq:tags","wknd-shared:activity/bulktagtest3;wknd-shared:activity/bulktagtest10"); + bulkPageTagger.tagPages(actionManager); + + } +} diff --git a/bundle/src/test/resources/com/adobe/acs/commons/mcp/impl/processes/bulkPageTagger.xlsx b/bundle/src/test/resources/com/adobe/acs/commons/mcp/impl/processes/bulkPageTagger.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..e62257641dc74fc425f90af0f7ad7287d279b812 GIT binary patch literal 9907 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 literal 0 HcmV?d00001 From e9ad2765376d1e2a929b26450fe8bf91838693fe Mon Sep 17 00:00:00 2001 From: Yegor Kozlov Date: Fri, 8 Sep 2023 22:11:14 +0200 Subject: [PATCH 2/6] #3147 - Fixed setting initial content-type when importing CFs from a spreadsheet (#3167) * #3147 - Fixed setting initial content-type when importing CFs from a spreadsheet --- CHANGELOG.md | 1 + .../processes/cfi/ContentFragmentImport.java | 24 +++++++------------ .../cfi/ContentFragmentImportTest.java | 2 -- .../processes/cfi/MockContentFragment.java | 14 ++++++++++- 4 files changed, 23 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1e1d247f9..0050eaa251 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com) - ## Unreleased ([details][unreleased changes details]) +- #3147 - Fixed setting initial content-type when importing CFs from a spreadsheet #3170 - Added a new MCP tool to bulk tag AEM content pages via an Excel file input. diff --git a/bundle/src/main/java/com/adobe/acs/commons/mcp/impl/processes/cfi/ContentFragmentImport.java b/bundle/src/main/java/com/adobe/acs/commons/mcp/impl/processes/cfi/ContentFragmentImport.java index 2510cf8a04..efe48f9ff5 100644 --- a/bundle/src/main/java/com/adobe/acs/commons/mcp/impl/processes/cfi/ContentFragmentImport.java +++ b/bundle/src/main/java/com/adobe/acs/commons/mcp/impl/processes/cfi/ContentFragmentImport.java @@ -33,7 +33,6 @@ import com.adobe.cq.dam.cfm.FragmentTemplate; import com.day.cq.commons.jcr.JcrConstants; import java.io.IOException; -import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; @@ -48,22 +47,17 @@ import javax.jcr.RepositoryException; import javax.jcr.Session; import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang3.reflect.MethodUtils; import org.apache.sling.api.request.RequestParameter; import org.apache.sling.api.resource.LoginException; import org.apache.sling.api.resource.PersistenceException; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ResourceResolver; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * Import a series of content fragments from a spreadsheet */ public class ContentFragmentImport extends ProcessDefinition { - private static final Logger LOG = LoggerFactory.getLogger(ContentFragmentImport.class); - public enum ReportColumns { ITEM, ACTION, DESCRIPTION, COUNT } @@ -313,8 +307,14 @@ private void setContentElements(ContentFragment cf, Map row, ContentElement conte protected ContentFragment getOrCreateFragment(Resource parent, Resource template, String name, String title) throws ContentFragmentException { Resource fragmentResource = parent.getChild(name); if (fragmentResource == null) { - try { - FragmentTemplate fragmentTemplate = template.adaptTo(FragmentTemplate.class); -// TODO: Replace this reflection hack with the proper method once ACS Commons doesn't support 6.2 anymore - return (ContentFragment) MethodUtils.invokeMethod(fragmentTemplate, "createFragment", parent, name, title); - } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ex) { - LOG.error("Unable to call createFragment method -- Is this 6.3 or newer?", ex); - return null; - } + FragmentTemplate fragmentTemplate = template.adaptTo(FragmentTemplate.class); + return fragmentTemplate.createFragment(parent, name, title); } else { return fragmentResource.adaptTo(ContentFragment.class); } diff --git a/bundle/src/test/java/com/adobe/acs/commons/mcp/impl/processes/cfi/ContentFragmentImportTest.java b/bundle/src/test/java/com/adobe/acs/commons/mcp/impl/processes/cfi/ContentFragmentImportTest.java index 07a1e4c13b..038ded4657 100644 --- a/bundle/src/test/java/com/adobe/acs/commons/mcp/impl/processes/cfi/ContentFragmentImportTest.java +++ b/bundle/src/test/java/com/adobe/acs/commons/mcp/impl/processes/cfi/ContentFragmentImportTest.java @@ -28,8 +28,6 @@ import java.util.Date; import java.time.OffsetDateTime; -import java.time.format.DateTimeFormatter; -import java.time.temporal.TemporalAccessor; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; diff --git a/bundle/src/test/java/com/adobe/acs/commons/mcp/impl/processes/cfi/MockContentFragment.java b/bundle/src/test/java/com/adobe/acs/commons/mcp/impl/processes/cfi/MockContentFragment.java index 8c7698bf3e..82cc8676e9 100644 --- a/bundle/src/test/java/com/adobe/acs/commons/mcp/impl/processes/cfi/MockContentFragment.java +++ b/bundle/src/test/java/com/adobe/acs/commons/mcp/impl/processes/cfi/MockContentFragment.java @@ -37,6 +37,10 @@ import org.apache.sling.api.resource.Resource; import org.jetbrains.annotations.NotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + /** * Incomplete mock that provides just enough for basic testing */ @@ -47,6 +51,14 @@ public class MockContentFragment implements ContentFragment { String path; HashMap elements = new HashMap<>(); HashMap metadata = new HashMap<>(); + FragmentTemplate template; + + public MockContentFragment(){ + template = mock(FragmentTemplate.class); + ElementTemplate elementTemplate = mock(ElementTemplate.class); + doReturn("text/html").when(elementTemplate).getInitialContentType(); + doReturn(elementTemplate).when(template).getForElement(any(ContentElement.class)); + } @Override public Iterator getElements() { @@ -114,7 +126,7 @@ public Iterator listAllVariations() { @Override public FragmentTemplate getTemplate() { - return null; + return template; } @Override From ad10e452281ef23021437f25d786d5c3193c29da Mon Sep 17 00:00:00 2001 From: Roy Teeuwen Date: Fri, 8 Sep 2023 22:18:49 +0200 Subject: [PATCH 3/6] Add page property injection (#3160) * Add page property injection --------- Co-authored-by: Roy Teeuwen --- CHANGELOG.md | 5 +- .../annotation/HierarchicalPageProperty.java | 14 +++-- .../injectors/annotation/PageProperty.java | 61 +++++++++++++++++++ .../HierarchicalPagePropertyInjector.java | 21 +++++-- .../HierarchicalPagePropertyInjectorTest.java | 20 +++--- .../TestHierarchicalPagePropertiesModel.java | 4 +- .../impl/model/TestPagePropertiesModel.java | 27 ++++++++ ...rarchicalPagePropertiesModelModelImpl.java | 12 +++- .../TestPagePropertiesModelModelImpl.java | 49 +++++++++++++++ .../injectors/impl/we-retail-pages.json | 3 + 10 files changed, 195 insertions(+), 21 deletions(-) create mode 100644 bundle/src/main/java/com/adobe/acs/commons/models/injectors/annotation/PageProperty.java create mode 100644 bundle/src/test/java/com/adobe/acs/commons/models/injectors/impl/model/TestPagePropertiesModel.java create mode 100644 bundle/src/test/java/com/adobe/acs/commons/models/injectors/impl/model/impl/TestPagePropertiesModelModelImpl.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 0050eaa251..408b3fe47a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,8 +11,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com) ## Unreleased ([details][unreleased changes details]) - #3147 - Fixed setting initial content-type when importing CFs from a spreadsheet -#3170 - Added a new MCP tool to bulk tag AEM content pages via an Excel file input. +## Added + +- #3159 - Add PageProperty annotation for Sling Models +- #3170 - Added a new MCP tool to bulk tag AEM content pages via an Excel file input. ## Fixed diff --git a/bundle/src/main/java/com/adobe/acs/commons/models/injectors/annotation/HierarchicalPageProperty.java b/bundle/src/main/java/com/adobe/acs/commons/models/injectors/annotation/HierarchicalPageProperty.java index a0b5b24808..a99caf95ba 100644 --- a/bundle/src/main/java/com/adobe/acs/commons/models/injectors/annotation/HierarchicalPageProperty.java +++ b/bundle/src/main/java/com/adobe/acs/commons/models/injectors/annotation/HierarchicalPageProperty.java @@ -18,6 +18,7 @@ package com.adobe.acs.commons.models.injectors.annotation; +import com.adobe.acs.commons.models.injectors.impl.HierarchicalPagePropertyInjector; import org.apache.commons.lang3.StringUtils; import org.apache.sling.models.annotations.Source; import org.apache.sling.models.annotations.injectorspecific.InjectionStrategy; @@ -39,14 +40,9 @@ @Target({METHOD, FIELD, PARAMETER}) @Retention(RUNTIME) @InjectAnnotation -@Source(HierarchicalPageProperty.SOURCE) +@Source(HierarchicalPagePropertyInjector.SOURCE) public @interface HierarchicalPageProperty { - /** - * Source value used for this annotation. - * @see Source - */ - String SOURCE = "hierarchical-page-property"; /** * Specifies the name of the value from the value map to take. @@ -54,6 +50,12 @@ */ String value() default StringUtils.EMPTY; + /** + * Specifies if it should use the hierarchy to search for the page property. + * If false, it will only look at the current page. + */ + boolean inherit() default true; + /** * if set to REQUIRED injection is mandatory, if set to OPTIONAL injection is optional, in case of DEFAULT * the standard annotations ({@link org.apache.sling.models.annotations.Optional}, {@link org.apache.sling.models.annotations.Required}) are used. diff --git a/bundle/src/main/java/com/adobe/acs/commons/models/injectors/annotation/PageProperty.java b/bundle/src/main/java/com/adobe/acs/commons/models/injectors/annotation/PageProperty.java new file mode 100644 index 0000000000..4e2f73a20c --- /dev/null +++ b/bundle/src/main/java/com/adobe/acs/commons/models/injectors/annotation/PageProperty.java @@ -0,0 +1,61 @@ +/* + * ACS AEM Commons + * + * Copyright (C) 2013 - 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.acs.commons.models.injectors.annotation; + + +import com.adobe.acs.commons.models.injectors.impl.HierarchicalPagePropertyInjector; +import org.apache.commons.lang3.StringUtils; +import org.apache.sling.models.annotations.Source; +import org.apache.sling.models.annotations.injectorspecific.InjectionStrategy; +import org.apache.sling.models.spi.injectorspecific.InjectAnnotation; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * Injects a page property. + * Note: not supported by the javax.Inject annotation because of performance reasons. Only direct annotation is supported. + */ +@Target({METHOD, FIELD, PARAMETER}) +@Retention(RUNTIME) +@InjectAnnotation +@Source(HierarchicalPagePropertyInjector.SOURCE) +public @interface PageProperty { + + + /** + * Specifies the name of the value from the value map to take. + * If empty, then the name is derived from the method or field. + */ + String value() default StringUtils.EMPTY; + + + /** + * if set to REQUIRED injection is mandatory, if set to OPTIONAL injection is optional, in case of DEFAULT + * the standard annotations ({@link org.apache.sling.models.annotations.Optional}, {@link org.apache.sling.models.annotations.Required}) are used. + * If even those are not available the default injection strategy defined on the {@link org.apache.sling.models.annotations.Model} applies. + * Default value = DEFAULT. + */ + InjectionStrategy injectionStrategy() default InjectionStrategy.DEFAULT; + +} diff --git a/bundle/src/main/java/com/adobe/acs/commons/models/injectors/impl/HierarchicalPagePropertyInjector.java b/bundle/src/main/java/com/adobe/acs/commons/models/injectors/impl/HierarchicalPagePropertyInjector.java index 37ef6c49ff..706784875c 100644 --- a/bundle/src/main/java/com/adobe/acs/commons/models/injectors/impl/HierarchicalPagePropertyInjector.java +++ b/bundle/src/main/java/com/adobe/acs/commons/models/injectors/impl/HierarchicalPagePropertyInjector.java @@ -18,11 +18,13 @@ package com.adobe.acs.commons.models.injectors.impl; import com.adobe.acs.commons.models.injectors.annotation.HierarchicalPageProperty; +import com.adobe.acs.commons.models.injectors.annotation.PageProperty; import com.adobe.acs.commons.util.impl.ReflectionUtil; import com.day.cq.commons.inherit.HierarchyNodeInheritanceValueMap; import com.day.cq.commons.inherit.InheritanceValueMap; import com.day.cq.wcm.api.Page; import org.apache.sling.api.resource.Resource; +import org.apache.sling.models.annotations.Source; import org.apache.sling.models.spi.DisposalCallbackRegistry; import org.apache.sling.models.spi.Injector; import org.osgi.framework.Constants; @@ -42,15 +44,22 @@ ) public class HierarchicalPagePropertyInjector implements Injector { + /** + * Source value used for injector + * + * @see Source + */ + public static final String SOURCE = "hierarchical-page-property"; + @Override public String getName() { - return HierarchicalPageProperty.SOURCE; + return SOURCE; } public Object getValue(Object adaptable, String name, Type declaredType, AnnotatedElement element, DisposalCallbackRegistry callbackRegistry) { - if (!element.isAnnotationPresent(HierarchicalPageProperty.class)) { + if (!(element.isAnnotationPresent(HierarchicalPageProperty.class) || element.isAnnotationPresent(PageProperty.class))) { //skipping javax.Inject for performance reasons. Only supports direct injection. return null; } @@ -59,8 +68,12 @@ public Object getValue(Object adaptable, String name, Type declaredType, Annotat if (currentResource != null) { Resource adaptableRes = lookUpFromPage(currentResource); if (adaptableRes != null) { - InheritanceValueMap inheritanceValueMap = new HierarchyNodeInheritanceValueMap(adaptableRes); - return ReflectionUtil.convertValueMapValue(inheritanceValueMap, name, declaredType); + if (element.isAnnotationPresent(PageProperty.class) || !element.getAnnotation(HierarchicalPageProperty.class).inherit()) { + return ReflectionUtil.convertValueMapValue(adaptableRes.getValueMap(), name, declaredType); + } else { + InheritanceValueMap inheritanceValueMap = new HierarchyNodeInheritanceValueMap(adaptableRes); + return ReflectionUtil.convertValueMapValue(inheritanceValueMap, name, declaredType); + } } } diff --git a/bundle/src/test/java/com/adobe/acs/commons/models/injectors/impl/HierarchicalPagePropertyInjectorTest.java b/bundle/src/test/java/com/adobe/acs/commons/models/injectors/impl/HierarchicalPagePropertyInjectorTest.java index fc0e57ecc9..2ad5625cc3 100644 --- a/bundle/src/test/java/com/adobe/acs/commons/models/injectors/impl/HierarchicalPagePropertyInjectorTest.java +++ b/bundle/src/test/java/com/adobe/acs/commons/models/injectors/impl/HierarchicalPagePropertyInjectorTest.java @@ -17,10 +17,11 @@ */ package com.adobe.acs.commons.models.injectors.impl; -import com.adobe.acs.commons.models.injectors.annotation.HierarchicalPageProperty; import com.adobe.acs.commons.models.injectors.annotation.impl.HierarchicalPagePropertyAnnotationProcessorFactory; import com.adobe.acs.commons.models.injectors.impl.model.TestHierarchicalPagePropertiesModel; +import com.adobe.acs.commons.models.injectors.impl.model.TestPagePropertiesModel; import com.adobe.acs.commons.models.injectors.impl.model.impl.TestHierarchicalPagePropertiesModelModelImpl; +import com.adobe.acs.commons.models.injectors.impl.model.impl.TestPagePropertiesModelModelImpl; import io.wcm.testing.mock.aem.junit.AemContext; import org.apache.sling.api.resource.Resource; import org.apache.sling.models.spi.Injector; @@ -32,8 +33,7 @@ import org.mockito.InjectMocks; import org.mockito.junit.MockitoJUnitRunner; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.*; @RunWith(MockitoJUnitRunner.class) public class HierarchicalPagePropertyInjectorTest { @@ -43,7 +43,8 @@ public class HierarchicalPagePropertyInjectorTest { @InjectMocks private HierarchicalPagePropertyInjector injector; - private TestHierarchicalPagePropertiesModel adapted; + private TestHierarchicalPagePropertiesModel hierarchicalModel; + private TestPagePropertiesModel pageModel; @Before public void setUp() throws Exception { @@ -53,19 +54,24 @@ public void setUp() throws Exception { context.registerService(Injector.class, injector); context.registerService(StaticInjectAnnotationProcessorFactory.class, new HierarchicalPagePropertyAnnotationProcessorFactory()); context.addModelsForClasses(TestHierarchicalPagePropertiesModelModelImpl.class); + context.addModelsForClasses(TestPagePropertiesModelModelImpl.class); Resource adaptable = context.request().getResource(); - adapted = adaptable.adaptTo(TestHierarchicalPagePropertiesModel.class); + hierarchicalModel = adaptable.adaptTo(TestHierarchicalPagePropertiesModel.class); + pageModel = adaptable.adaptTo(TestPagePropertiesModel.class); } @Test public void test_name() { - assertEquals(HierarchicalPageProperty.SOURCE, injector.getName()); + assertEquals(HierarchicalPagePropertyInjector.SOURCE, injector.getName()); } @Test public void test() { - assertNotNull(adapted); + assertNotNull(hierarchicalModel); + assertEquals("inherited!", hierarchicalModel.getHierarchicalPagePropertyString()); + assertNull(pageModel.getHierarchicalPagePropertyString()); + assertEquals("not inherited", hierarchicalModel.getPagePropertyString()); } diff --git a/bundle/src/test/java/com/adobe/acs/commons/models/injectors/impl/model/TestHierarchicalPagePropertiesModel.java b/bundle/src/test/java/com/adobe/acs/commons/models/injectors/impl/model/TestHierarchicalPagePropertiesModel.java index 4365350c2b..b38acaebb2 100644 --- a/bundle/src/test/java/com/adobe/acs/commons/models/injectors/impl/model/TestHierarchicalPagePropertiesModel.java +++ b/bundle/src/test/java/com/adobe/acs/commons/models/injectors/impl/model/TestHierarchicalPagePropertiesModel.java @@ -23,7 +23,9 @@ public interface TestHierarchicalPagePropertiesModel { - String getPropertyString(); + String getPagePropertyString(); + + String getHierarchicalPagePropertyString(); String getUndefinedProperty(); diff --git a/bundle/src/test/java/com/adobe/acs/commons/models/injectors/impl/model/TestPagePropertiesModel.java b/bundle/src/test/java/com/adobe/acs/commons/models/injectors/impl/model/TestPagePropertiesModel.java new file mode 100644 index 0000000000..757d52cfc2 --- /dev/null +++ b/bundle/src/test/java/com/adobe/acs/commons/models/injectors/impl/model/TestPagePropertiesModel.java @@ -0,0 +1,27 @@ +/* + * ACS AEM Commons + * + * Copyright (C) 2013 - 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.acs.commons.models.injectors.impl.model; + + +public interface TestPagePropertiesModel { + + String getPagePropertyString(); + + String getHierarchicalPagePropertyString(); + +} diff --git a/bundle/src/test/java/com/adobe/acs/commons/models/injectors/impl/model/impl/TestHierarchicalPagePropertiesModelModelImpl.java b/bundle/src/test/java/com/adobe/acs/commons/models/injectors/impl/model/impl/TestHierarchicalPagePropertiesModelModelImpl.java index b786963cdb..ae255f5284 100644 --- a/bundle/src/test/java/com/adobe/acs/commons/models/injectors/impl/model/impl/TestHierarchicalPagePropertiesModelModelImpl.java +++ b/bundle/src/test/java/com/adobe/acs/commons/models/injectors/impl/model/impl/TestHierarchicalPagePropertiesModelModelImpl.java @@ -34,10 +34,13 @@ ) public class TestHierarchicalPagePropertiesModelModelImpl implements TestHierarchicalPagePropertiesModel { + @HierarchicalPageProperty + private String pagePropertyString; + @HierarchicalPageProperty private String hierarchicalPagePropertyString; - @HierarchicalPageProperty("hierarchicalPagePropertyBoolean") + @HierarchicalPageProperty(value = "hierarchicalPagePropertyBoolean", inherit = false) private boolean hierarchicalPagePropertyBoolean; @HierarchicalPageProperty @@ -63,7 +66,12 @@ public class TestHierarchicalPagePropertiesModelModelImpl implements TestHierarc @Override - public String getPropertyString() { + public String getPagePropertyString() { + return pagePropertyString; + } + + @Override + public String getHierarchicalPagePropertyString() { return hierarchicalPagePropertyString; } diff --git a/bundle/src/test/java/com/adobe/acs/commons/models/injectors/impl/model/impl/TestPagePropertiesModelModelImpl.java b/bundle/src/test/java/com/adobe/acs/commons/models/injectors/impl/model/impl/TestPagePropertiesModelModelImpl.java new file mode 100644 index 0000000000..7faa5d76c4 --- /dev/null +++ b/bundle/src/test/java/com/adobe/acs/commons/models/injectors/impl/model/impl/TestPagePropertiesModelModelImpl.java @@ -0,0 +1,49 @@ +/* + * ACS AEM Commons + * + * Copyright (C) 2013 - 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.acs.commons.models.injectors.impl.model.impl; + +import com.adobe.acs.commons.models.injectors.annotation.PageProperty; +import com.adobe.acs.commons.models.injectors.impl.model.TestPagePropertiesModel; +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.api.resource.Resource; +import org.apache.sling.models.annotations.DefaultInjectionStrategy; +import org.apache.sling.models.annotations.Model; + +@Model( + adapters = TestPagePropertiesModel.class, + adaptables = {SlingHttpServletRequest.class, Resource.class}, + defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL +) +public class TestPagePropertiesModelModelImpl implements TestPagePropertiesModel { + + @PageProperty + private String hierarchicalPagePropertyString; + @PageProperty + private String pagePropertyString; + + @Override + public String getPagePropertyString() { + return pagePropertyString; + } + + @Override + public String getHierarchicalPagePropertyString() { + return hierarchicalPagePropertyString; + } + +} diff --git a/bundle/src/test/resources/com/adobe/acs/commons/models/injectors/impl/we-retail-pages.json b/bundle/src/test/resources/com/adobe/acs/commons/models/injectors/impl/we-retail-pages.json index 6a80e34a7d..6baabc8f61 100644 --- a/bundle/src/test/resources/com/adobe/acs/commons/models/injectors/impl/we-retail-pages.json +++ b/bundle/src/test/resources/com/adobe/acs/commons/models/injectors/impl/we-retail-pages.json @@ -7,6 +7,7 @@ "cq:template": "/conf/we-retail/settings/wcm/templates/hero-page", "cq:designPath": "/etc/designs/acs-commons", "hierarchicalPagePropertyString": "inherited!", + "pagePropertyString": "inherited!", "hierarchicalPagePropertyBoolean": true, "hierarchicalPagePropertyInteger": 11, "hierarchicalPagePropertyMultiValueInteger": [ @@ -168,6 +169,8 @@ "cq:lastModified": "Tue Nov 06 2018 11:00:39 GMT+0100", "sling:resourceType": "weretail/components/structure/page", "cq:lastModifiedBy": "admin", + "pagePropertyString": "not inherited", + "hierarchicalPagePropertyBoolean": false, "root": { "jcr:primaryType": "nt:unstructured", "sling:resourceType": "wcm/foundation/components/responsivegrid", From 2f4ececbfef5b5c4659e1ea97bd6ddca55b78c9f Mon Sep 17 00:00:00 2001 From: david g Date: Fri, 8 Sep 2023 16:22:18 -0400 Subject: [PATCH 4/6] Update CHANGELOG.md --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 408b3fe47a..571a10cd0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,8 +9,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com) - ## Unreleased ([details][unreleased changes details]) -- #3147 - Fixed setting initial content-type when importing CFs from a spreadsheet +## 6.1.0 - 2023-09-08 ## Added @@ -19,6 +19,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com) ## Fixed +- #3147 - Fixed setting initial content-type when importing CFs from a spreadsheet - #3040 - Fixed bug where namespaced multi-fields would have the namespace 2 times - #3140 - Fixed issue where malformed MCP process nodes can cause a NPE that breaks the entire MPC reporting UI. Now displays more friendly values in UI to help remove the invalid nodes. - #3150 - Support for case-insensitive redirect rules ( [NC] flag equivalent of apache) From 79ab882d3b164367570929709ea4e68d6d6ef5e2 Mon Sep 17 00:00:00 2001 From: david g Date: Fri, 8 Sep 2023 16:24:37 -0400 Subject: [PATCH 5/6] [maven-release-plugin] prepare release acs-aem-commons-6.1.0 --- all/pom.xml | 2 +- bundle/pom.xml | 2 +- oakpal-checks/pom.xml | 2 +- pom.xml | 6 +++--- ui.apps/pom.xml | 2 +- ui.content/pom.xml | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/all/pom.xml b/all/pom.xml index 316f7f5b33..060bea5f2f 100644 --- a/all/pom.xml +++ b/all/pom.xml @@ -25,7 +25,7 @@ com.adobe.acs acs-aem-commons - 6.0.15-SNAPSHOT + 6.1.0 diff --git a/bundle/pom.xml b/bundle/pom.xml index 43f83c3c3e..f3e1413b18 100644 --- a/bundle/pom.xml +++ b/bundle/pom.xml @@ -25,7 +25,7 @@ com.adobe.acs acs-aem-commons - 6.0.15-SNAPSHOT + 6.1.0 diff --git a/oakpal-checks/pom.xml b/oakpal-checks/pom.xml index 0259a6bdfe..16ca4b0aab 100644 --- a/oakpal-checks/pom.xml +++ b/oakpal-checks/pom.xml @@ -25,7 +25,7 @@ com.adobe.acs acs-aem-commons - 6.0.15-SNAPSHOT + 6.1.0 diff --git a/pom.xml b/pom.xml index df76f9f47d..39135a38e1 100644 --- a/pom.xml +++ b/pom.xml @@ -25,7 +25,7 @@ com.adobe.acs acs-aem-commons - 6.0.15-SNAPSHOT + 6.1.0 pom ACS AEM Commons - Reactor Project @@ -49,7 +49,7 @@ scm:git:git@github.com:Adobe-Consulting-Services/acs-aem-commons.git scm:git:git@github.com:Adobe-Consulting-Services/acs-aem-commons.git https://github.com/Adobe-Consulting-Services/acs-aem-commons/tree/master - acs-aem-commons-5.5.0 + acs-aem-commons-6.1.0 @@ -88,7 +88,7 @@ 1.8 1.8 - 1689084806 + 1694204582 diff --git a/ui.apps/pom.xml b/ui.apps/pom.xml index 09a79d924d..4cea8f843f 100644 --- a/ui.apps/pom.xml +++ b/ui.apps/pom.xml @@ -25,7 +25,7 @@ com.adobe.acs acs-aem-commons - 6.0.15-SNAPSHOT + 6.1.0 diff --git a/ui.content/pom.xml b/ui.content/pom.xml index 861c9c86b1..1e819044f7 100644 --- a/ui.content/pom.xml +++ b/ui.content/pom.xml @@ -25,7 +25,7 @@ com.adobe.acs acs-aem-commons - 6.0.15-SNAPSHOT + 6.1.0 From a75bb2920aeefb274e3d89b32b65b6293b704822 Mon Sep 17 00:00:00 2001 From: david g Date: Fri, 8 Sep 2023 16:24:39 -0400 Subject: [PATCH 6/6] [maven-release-plugin] prepare for next development iteration --- all/pom.xml | 2 +- bundle/pom.xml | 2 +- oakpal-checks/pom.xml | 2 +- pom.xml | 6 +++--- ui.apps/pom.xml | 2 +- ui.content/pom.xml | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/all/pom.xml b/all/pom.xml index 060bea5f2f..098119bbd4 100644 --- a/all/pom.xml +++ b/all/pom.xml @@ -25,7 +25,7 @@ com.adobe.acs acs-aem-commons - 6.1.0 + 6.1.1-SNAPSHOT diff --git a/bundle/pom.xml b/bundle/pom.xml index f3e1413b18..c0d2b8c9ec 100644 --- a/bundle/pom.xml +++ b/bundle/pom.xml @@ -25,7 +25,7 @@ com.adobe.acs acs-aem-commons - 6.1.0 + 6.1.1-SNAPSHOT diff --git a/oakpal-checks/pom.xml b/oakpal-checks/pom.xml index 16ca4b0aab..75c32575f5 100644 --- a/oakpal-checks/pom.xml +++ b/oakpal-checks/pom.xml @@ -25,7 +25,7 @@ com.adobe.acs acs-aem-commons - 6.1.0 + 6.1.1-SNAPSHOT diff --git a/pom.xml b/pom.xml index 39135a38e1..167e1cbffd 100644 --- a/pom.xml +++ b/pom.xml @@ -25,7 +25,7 @@ com.adobe.acs acs-aem-commons - 6.1.0 + 6.1.1-SNAPSHOT pom ACS AEM Commons - Reactor Project @@ -49,7 +49,7 @@ scm:git:git@github.com:Adobe-Consulting-Services/acs-aem-commons.git scm:git:git@github.com:Adobe-Consulting-Services/acs-aem-commons.git https://github.com/Adobe-Consulting-Services/acs-aem-commons/tree/master - acs-aem-commons-6.1.0 + acs-aem-commons-5.5.0 @@ -88,7 +88,7 @@ 1.8 1.8 - 1694204582 + 1694204679 diff --git a/ui.apps/pom.xml b/ui.apps/pom.xml index 4cea8f843f..5a036d06cb 100644 --- a/ui.apps/pom.xml +++ b/ui.apps/pom.xml @@ -25,7 +25,7 @@ com.adobe.acs acs-aem-commons - 6.1.0 + 6.1.1-SNAPSHOT diff --git a/ui.content/pom.xml b/ui.content/pom.xml index 1e819044f7..45ff9b0550 100644 --- a/ui.content/pom.xml +++ b/ui.content/pom.xml @@ -25,7 +25,7 @@ com.adobe.acs acs-aem-commons - 6.1.0 + 6.1.1-SNAPSHOT