Henry Kuijpers created SLING-7257:
-------------------------------------
Summary: Sling Models injector for resolving paths stored in the
repo
Key: SLING-7257
URL: https://issues.apache.org/jira/browse/SLING-7257
Project: Sling
Issue Type: New Feature
Affects Versions: Sling Models Impl 1.4.4
Reporter: Henry Kuijpers
It would be great to have the ability to store paths in the repository (as a
string or as a string array) and then resolve them with a simple annotation,
instead of having a lot of code in the specific models to do so.
I started working on something that for now only supports resources and tags,
but I think it should actually be possible to delegate the execution of
transforming the resource to any object, using the injectors that are already
available.
I'm not sure if what I made is the way to go, but at least it's a starting
point?
Injector:
{code}
@Component
@Slf4j
public class ResolvePathInjector implements InjectAnnotationProcessorFactory2,
Injector {
@Override
public String getName() {
return "resolve-path";
}
@Override
public Object getValue(Object adaptable, String name, Type declaredType,
AnnotatedElement element,
DisposalCallbackRegistry callbackRegistry) {
final ResolvePath annotation = element.getAnnotation(ResolvePath.class);
if (annotation == null) {
return null;
}
final Resource resource = getResource(adaptable);
if (resource == null) {
throw new IllegalArgumentException("Cannot get resource resolver
from adaptable");
}
final String[] paths = getPaths(annotation, resource);
if (paths == null) {
return null;
}
return getValue(paths, declaredType, resource.getResourceResolver());
}
private static String[] getPaths(ResolvePath annotation, Resource resource)
{
final ValueMap map = resource.adaptTo(ValueMap.class);
if (map == null) {
return null;
}
final String[] paths = map.get(annotation.name(), String[].class);
if (paths == null || paths.length == 0) {
return null;
}
return paths;
}
private static Object getValue(String[] paths, Type declaredType,
ResourceResolver resourceResolver) {
// TODO: Support more injections! I.e. other sling models
final boolean isTagArray = declaredType == Tag[].class;
final boolean isTag = declaredType == Tag.class;
if (!isTag && !isTagArray) {
return null;
}
final List<Tag> tags = new ArrayList<>();
final TagManager tagManager =
resourceResolver.adaptTo(TagManager.class);
if (tagManager != null) {
for (String path : paths) {
final Tag tag = tagManager.resolve(path);
if (tag != null) {
tags.add(tag);
}
}
}
if (isTag && !tags.isEmpty()) {
return tags.get(0);
}
return tags.toArray(new Tag[tags.size()]);
}
private static Resource getResource(Object adaptable) {
Resource resource = null;
if (adaptable instanceof Resource) {
resource = (Resource) adaptable;
} else if (adaptable instanceof SlingHttpServletRequest) {
resource = ((SlingHttpServletRequest) adaptable).getResource();
} else if (adaptable instanceof Adaptable) {
resource = ((Adaptable)adaptable).adaptTo(Resource.class);
}
return resource;
}
@Override
public InjectAnnotationProcessor2 createAnnotationProcessor(Object
adaptable, AnnotatedElement element) {
// check if the element has the expected annotation
ResolvePath annotation = element.getAnnotation(ResolvePath.class);
if (annotation != null) {
return new ValueAnnotationProcessor(annotation, adaptable);
}
return null;
}
}
{code}
Annotation:
{code}
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
@InjectAnnotation
@Source("resolve-path")
@Qualifier
public @interface ResolvePath {
String name() default "";
InjectionStrategy injectionStrategy() default InjectionStrategy.DEFAULT;
String via() default "";
}
{code}
--
This message was sent by Atlassian JIRA
(v6.4.14#64029)