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)

Reply via email to