Package com.cognifide.slice.core.internal.module

Source Code of com.cognifide.slice.core.internal.module.SliceResourceModule$SliceResourceTypeListener

package com.cognifide.slice.core.internal.module;

import java.util.HashMap;
import java.util.Map;

import org.apache.sling.api.resource.Resource;

import com.cognifide.slice.api.model.InitializableModel;
import com.cognifide.slice.core.internal.provider.CurrentResourceProvider;
import com.cognifide.slice.mapper.annotation.SliceResource;
import com.cognifide.slice.mapper.api.Mapper;
import com.google.inject.AbstractModule;
import com.google.inject.Provider;
import com.google.inject.TypeLiteral;
import com.google.inject.matcher.AbstractMatcher;
import com.google.inject.spi.InjectionListener;
import com.google.inject.spi.TypeEncounter;
import com.google.inject.spi.TypeListener;

/**
* This module creates an InjectorListener that postprocesses every injection of a {@code @SliceResource},
* maps its {@code @JcrProperty} fields and invokes {@code afterCreated()} method.
*
* @author Tomasz Rękawek
*
*/
public class SliceResourceModule extends AbstractModule {

  private final SliceResourceAnnotationCache annotationCache = new SliceResourceAnnotationCache();

  @Override
  protected void configure() {
    final Provider<CurrentResourceProvider> currentResourceProvider = getProvider(CurrentResourceProvider.class);
    final Provider<Mapper> mapperProvider = getProvider(Mapper.class);

    // listener that checks if given injectee is annotated with @SliceResource
    AbstractMatcher<TypeLiteral<?>> matcher = new AbstractMatcher<TypeLiteral<?>>() {
      @Override
      public boolean matches(TypeLiteral<?> t) {
        return annotationCache.annotationPresent(t.getRawType());
      }
    };
    // register SliceResourceTypeListener for classes matched with matcher
    TypeListener listener = new TypeListener() {
      @Override
      public <I> void hear(final TypeLiteral<I> type, final TypeEncounter<I> encounter) {
        encounter.register(new SliceResourceTypeListener(currentResourceProvider, mapperProvider));
      }
    };
    bindListener(matcher, listener);
  }

  private static class SliceResourceTypeListener implements InjectionListener<Object> {

    private final Provider<CurrentResourceProvider> currentResourceProvider;

    private final Provider<Mapper> mapperProvider;

    public SliceResourceTypeListener(Provider<CurrentResourceProvider> currentResourceProvider,
        Provider<Mapper> mapperProvider) {
      this.currentResourceProvider = currentResourceProvider;
      this.mapperProvider = mapperProvider;
    }

    @Override
    public void afterInjection(Object injectee) {
      Resource resource = currentResourceProvider.get().get();
      if (resource == null) {
        return;
      }
      Mapper mapper = mapperProvider.get();
      mapper.get(resource, injectee);
      if (injectee instanceof InitializableModel) {
        ((InitializableModel) injectee).afterCreated();
      }
    }
  }

  private static class SliceResourceAnnotationCache {
    private Map<Class<?>, Boolean> cache = new HashMap<Class<?>, Boolean>();

    public boolean annotationPresent(Class<?> clazz) {
      if (!cache.containsKey(clazz)) {
        cache.put(clazz, clazz.isAnnotationPresent(SliceResource.class));
      }
      return cache.get(clazz);
    }
  }
}
TOP

Related Classes of com.cognifide.slice.core.internal.module.SliceResourceModule$SliceResourceTypeListener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.