Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Page injector updates #3304

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,27 @@
public @interface HierarchicalPageProperty {


/**
* Start traversing upwards in the hierarchy from a specific level, skipping lower levels.
* @since 6.0.16
* @see https://developer.adobe.com/experience-manager/reference-materials/6-5/javadoc/com/day/cq/wcm/api/Page.html#getAbsoluteParent-int-
* | level | returned |
* | 0 | /content |
* | 1 | /content/geometrixx |
* | 2 | /content/geometrixx/en |
* | 3 | /content/geometrixx/en/products |
* | 4 | null
* If we'd use 1 in this example, we would skip over level 2 and 3.
* -1 means we disable this value.
*/
int traverseFromAbsoluteParent() default -1;

/**
* Whether to use the current page (true) or the resource page (false).
* @return
*/
boolean useCurrentPage() default false;

/**
* Specifies the name of the value from the value map to take.
* If empty, then the name is derived from the method or field.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@
@Source(HierarchicalPagePropertyInjector.SOURCE)
public @interface PageProperty {

/**
* Whether to use the current page (true) or the resource page (false).
* @return
*/
boolean useCurrentPage() default false;

/**
* Specifies the name of the value from the value map to take.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*-
* #%L
* ACS AEM Commons Bundle
* %%
* Copyright (C) 2013 - 2024 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.models.injectors.annotation.impl;

import com.adobe.acs.commons.models.injectors.annotation.HierarchicalPageProperty;
import com.adobe.acs.commons.models.injectors.annotation.PageProperty;
import org.apache.sling.models.annotations.injectorspecific.InjectionStrategy;
import org.apache.sling.models.spi.injectorspecific.AbstractInjectAnnotationProcessor2;
import org.apache.sling.models.spi.injectorspecific.InjectAnnotationProcessor2;
import org.apache.sling.models.spi.injectorspecific.StaticInjectAnnotationProcessorFactory;
import org.osgi.service.component.annotations.Component;

import java.lang.reflect.AnnotatedElement;
import java.util.Optional;

import static org.apache.commons.lang3.StringUtils.isBlank;

/**
* The annotation processor for the {@link HierarchicalPageProperty} annotation
* <p>
* Note: This can only be used together with Sling Models API bundle in version 1.2.0 (due to the dependency on InjectionStrategy)
*/
@Component(service = StaticInjectAnnotationProcessorFactory.class)
public class PagePropertyAnnotationProcessorFactory implements StaticInjectAnnotationProcessorFactory {

@Override
public InjectAnnotationProcessor2 createAnnotationProcessor(AnnotatedElement element) {
return Optional.ofNullable(element.getAnnotation(PageProperty.class)).map(PagePropertyAnnotationProcessor::new).orElse(null);
}

private class PagePropertyAnnotationProcessor extends AbstractInjectAnnotationProcessor2 {
private final PageProperty annotation;

public PagePropertyAnnotationProcessor(PageProperty annotation) {
this.annotation = annotation;
}

@Override
public InjectionStrategy getInjectionStrategy() {
return annotation.injectionStrategy();
}

@Override
public String getName() {
if (isBlank(annotation.value())) {
return null;
}
return annotation.value();
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,19 @@
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.api.resource.ValueMap;
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;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Type;

import static com.adobe.acs.commons.models.injectors.impl.InjectorUtils.getResource;
import static com.adobe.acs.commons.models.injectors.impl.InjectorUtils.getResourcePage;
import static com.adobe.acs.commons.models.injectors.impl.InjectorUtils.*;

@Component(
property = {
Expand All @@ -51,6 +53,8 @@ public class HierarchicalPagePropertyInjector implements Injector {
*/
public static final String SOURCE = "hierarchical-page-property";

private static final Logger LOG = LoggerFactory.getLogger(HierarchicalPagePropertyInjector.class);

@Override
public String getName() {
return SOURCE;
Expand All @@ -66,13 +70,13 @@ public Object getValue(Object adaptable, String name, Type declaredType, Annotat

Resource currentResource = getResource(adaptable);
if (currentResource != null) {
Resource adaptableRes = lookUpFromPage(currentResource);
Resource adaptableRes = lookUpFromPage(adaptable, currentResource, element);
if (adaptableRes != null) {
if (element.isAnnotationPresent(PageProperty.class) || !element.getAnnotation(HierarchicalPageProperty.class).inherit()) {
return ReflectionUtil.convertValueMapValue(adaptableRes.getValueMap(), name, declaredType);
} else {
if (useInheritance(element)) {
InheritanceValueMap inheritanceValueMap = new HierarchyNodeInheritanceValueMap(adaptableRes);
return ReflectionUtil.convertValueMapValue(inheritanceValueMap, name, declaredType);
} else {
return ReflectionUtil.convertValueMapValue(adaptableRes.getValueMap(), name, declaredType);
}
}

Expand All @@ -81,10 +85,45 @@ public Object getValue(Object adaptable, String name, Type declaredType, Annotat

}

private Resource lookUpFromPage(Resource currentResource) {
Page containingPage = getResourcePage(currentResource);
private Resource lookUpFromPage(Object adaptable, Resource currentResource, AnnotatedElement element) {

boolean useCurrentPage = useCurrentPage(element);
Page containingPage;

if(useCurrentPage){
containingPage = getCurrentPage(adaptable);
if(containingPage == null){
LOG.error("Could not find current page for resource: {}. Only SlingHttpServletRequest is supported as adaptable", getResource(adaptable).getPath());
}
}else{
containingPage = getResourcePage(currentResource);
}

if(containingPage != null && element.isAnnotationPresent(HierarchicalPageProperty.class)) {
HierarchicalPageProperty annotation = element.getAnnotation(HierarchicalPageProperty.class);
if(annotation.traverseFromAbsoluteParent() > -1){
containingPage = containingPage.getAbsoluteParent(annotation.traverseFromAbsoluteParent());
}
}

return containingPage != null ? containingPage.getContentResource() : null;
}


private boolean useCurrentPage(AnnotatedElement element){

if(element.isAnnotationPresent(HierarchicalPageProperty.class)){
return element.getAnnotation(HierarchicalPageProperty.class).useCurrentPage();
}else if (element.isAnnotationPresent(PageProperty.class)){
return element.getAnnotation(PageProperty.class).useCurrentPage();
}
return false;

}

private boolean useInheritance(AnnotatedElement element){
return element.isAnnotationPresent(HierarchicalPageProperty.class) && element.getAnnotation(HierarchicalPageProperty.class).inherit();
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*-
* #%L
* ACS AEM Commons Bundle
* %%
* Copyright (C) 2013 - 2024 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.models.via.annotations;

import org.apache.sling.models.annotations.ViaProviderType;

public interface PageContentResourceViaType extends ViaProviderType {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*-
* #%L
* ACS AEM Commons Bundle
* %%
* Copyright (C) 2013 - 2024 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%
*/
@org.osgi.annotation.versioning.Version("1.0.0")
package com.adobe.acs.commons.models.via.annotations;



Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*-
* #%L
* ACS AEM Commons Bundle
* %%
* Copyright (C) 2013 - 2024 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.models.via.impl;


import com.adobe.acs.commons.models.via.annotations.PageContentResourceViaType;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.ViaProviderType;
import org.apache.sling.models.spi.ViaProvider;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static com.adobe.acs.commons.models.injectors.impl.InjectorUtils.*;
import static com.adobe.acs.commons.models.injectors.impl.InjectorUtils.getResource;

@Component(service = ViaProvider.class)
public class PageContentResourceViaProvider implements ViaProvider {

public static final String VIA_CURRENT_PAGE = "currentPage";

private static final Logger logger = LoggerFactory.getLogger(PageContentResourceViaProvider.class);

@Override
public Class<? extends ViaProviderType> getType() {
return PageContentResourceViaType.class;
}

@Override
public Object getAdaptable(Object original, String value) {


try{
final Resource resource;

if(StringUtils.equals(value, VIA_CURRENT_PAGE)){
resource = getCurrentPage(original).getContentResource();

if(resource == null){
logger.error("Could not find current page for resource: {}. Only SlingHttpServletRequest is supported as adaptable", getResource(original).getPath());
}
}else{
resource = getResourcePage(original).getContentResource();
}

return resource;

}catch(NullPointerException ex){
logger.error("Error while getting content policy properties", ex);
}

return null;

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
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.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.spi.Injector;
import org.apache.sling.models.spi.injectorspecific.StaticInjectAnnotationProcessorFactory;
Expand All @@ -48,17 +49,10 @@ public class HierarchicalPagePropertyInjectorTest {

@Before
public void setUp() throws Exception {
context.currentPage("/content/we-retail/language-masters/en/experience/arctic-surfing-in-lofoten");
context.currentResource("/content/we-retail/language-masters/en/experience/arctic-surfing-in-lofoten/jcr:content/root");

context.registerService(Injector.class, injector);
context.registerService(StaticInjectAnnotationProcessorFactory.class, new HierarchicalPagePropertyAnnotationProcessorFactory());
context.addModelsForClasses(TestHierarchicalPagePropertiesModelModelImpl.class);
context.addModelsForClasses(TestPagePropertiesModelModelImpl.class);

Resource adaptable = context.request().getResource();
hierarchicalModel = adaptable.adaptTo(TestHierarchicalPagePropertiesModel.class);
pageModel = adaptable.adaptTo(TestPagePropertiesModel.class);
}

@Test
Expand All @@ -68,11 +62,19 @@ public void test_name() {

@Test
public void test() {

context.currentPage("/content/we-retail/language-masters/en/experience");
context.currentResource("/content/we-retail/language-masters/en/experience/arctic-surfing-in-lofoten/jcr:content/root");

SlingHttpServletRequest adaptable = context.request();
hierarchicalModel = adaptable.adaptTo(TestHierarchicalPagePropertiesModel.class);
pageModel = adaptable.adaptTo(TestPagePropertiesModel.class);

assertNotNull(hierarchicalModel);
assertEquals("inherited!", hierarchicalModel.getHierarchicalPagePropertyString());
assertNull(pageModel.getHierarchicalPagePropertyString());
assertEquals("not inherited", hierarchicalModel.getPagePropertyString());
}


assertEquals("inherited!", hierarchicalModel.getSkipLevelHierarchicalPagePropertyString());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,14 @@ public interface TestHierarchicalPagePropertiesModel {

String getPagePropertyString();

String getSkipLevelHierarchicalPagePropertyString();

String getCurrentPagePropertyString();

String getHierarchicalPagePropertyString();

String getCurrentPageHierarchicalPagePropertyString();

String getUndefinedProperty();

boolean getPropertyBoolean();
Expand Down
Loading
Loading