In this article, let's create an annotation to get the Multifield authored information and put the data into a List variable.
As can be seen on the Multifield documentation, when the component is using it into the Authoring Dialog, the values are stored into child nodes. The annotation will get it and iterate over the children. In this example, we will provide into the Annotation argument, the properties from the multifield node we would like to get.
Below you can see the structure of the component multifield content on the JCR tree:
my-component-node
multifield-property
item-0
item-1
item-2
item-3
<sly data-sly-use.component="com.rheck.aem.models.MyComponent">
<ul>
<sly data-sly-list="${component.listItems}">
<li data-sly-test="${item.link}">
<a href="${item.link @ extension='html'}">
<span>${item.label}</span>
</a>
</li>
</sly>
</ul>
</sly>
package com.rheck.aem.models;
import ...;
@Model(
adaptables = SlingHttpServletRequest.class,
defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL
)
public class MyComponent {
@Multifield(name = "multifield-property", values = {"label", "link"})
private List<HashMap> listItems;
public List<HashMap> getListItems() {
return listItems;
}
}
With all set, let's create the annotation and the injector, to make the annotation work.
package com.rheck.aem.provider;
import ...;
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@InjectAnnotation
@Source("page-multifield-provider-injector")
public @interface Multifield {
String[] values() default {};
String name() default "";
}
package com.rheck.aem.provider;
import ...;
@Component(
immediate = true, service = {Injector.class, StaticInjectAnnotationProcessorFactory.class},
property = {Constants.SERVICE_RANKING + ":Integer=7000"})
public class MultifieldInjector implements Injector, StaticInjectAnnotationProcessorFactory {
@Override
public Object getValue(Object adaptable, String fieldName, Type type, AnnotatedElement annotatedElement, DisposalCallbackRegistry disposalCallbackRegistry) {
if (adaptable instanceof SlingHttpServletRequest && annotatedElement.isAnnotationPresent(Multifield.class)) {
Multifield annotation = annotatedElement.getAnnotation(Multifield.class);
try {
Resource resource = ((SlingHttpServletRequest) adaptable).getResource();
Node multifieldNode = resource.adaptTo(Node.class);
if (multifieldNode == null) {
return null;
}
if (!multifieldNode.hasNode(annotation.name())) {
return new ArrayList<HashMap>();
}
return getMultifield(resource.getChild(annotation.name()), annotation.values());
} catch (Exception ex) {
ex.printStackTrace();
}
}
return null;
}
public void getMultifield(Resource resource, String[] fields) {
Node resourceNode = resource.adaptTo(Node.class);
NodeIterator ni = resourceNode.getNodes();
List<HashMap> multifield = new ArrayList<>();
while (ni.hasNext()) {
HashMap<String, String> values = new HashMap<>();
Node currentNode = (Node) ni.nextNode();
for (String field : fields) {
if (currentNode.hasProperty(field)) {
values.put(field, currentNode.getProperty(field).getString());
}
}
multifield.add(values);
}
return multifield;
}
@Override
public String getName() {
return "page-multifield-provider-injector";
}
@Override
public InjectAnnotationProcessor2 createAnnotationProcessor(AnnotatedElement element) {
MultiFieldProvider annotation = element.getAnnotation(Multifield.class);
if (annotation != null) {
return new RequestedPageMetadataProviderAnnotationProcessor();
}
return null;
}
private static class RequestedPageMetadataProviderAnnotationProcessor extends AbstractInjectAnnotationProcessor2 {
@Override
public InjectionStrategy getInjectionStrategy() {
return InjectionStrategy.DEFAULT;
}
@Override
public Boolean isOptional() {
return Boolean.FALSE;
}
}
}
All done. The annotation has been created and the injector will work executing the needed job.
No comments:
Post a Comment
If you have any doubts or questions, please let us know.