package org.tynamo.internal.services; import org.apache.commons.lang.StringUtils; import org.apache.tapestry5.internal.beaneditor.BeanModelUtils; import org.apache.tapestry5.ioc.annotations.PostInjection; import org.apache.tapestry5.ioc.internal.util.CollectionFactory; import org.apache.tapestry5.services.ComponentClasses; import org.apache.tapestry5.services.InvalidationEventHub; import org.apache.tapestry5.services.InvalidationListener; import org.apache.tapestry5.services.RequestGlobals; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.tynamo.PageType; import org.tynamo.descriptor.annotation.beaneditor.BeanModel; import org.tynamo.mixins.BeanModelAdvisor; import org.tynamo.services.BeanModelModifier; import java.util.HashMap; import java.util.Map; public class BeanModelsAnnotationBMModifier implements BeanModelModifier, InvalidationListener { private final static String defaultKey = PageType.DEFAULT.getContextKey(); private final static Logger logger = LoggerFactory.getLogger(BeanModelAdvisor.class); private final RequestGlobals globals; private final Map<String, Map<Class, Map<String, BeanModel>>> beanModels = CollectionFactory.newConcurrentMap(); public BeanModelsAnnotationBMModifier(RequestGlobals globals) { this.globals = globals; } @Override public boolean modify(org.apache.tapestry5.beaneditor.BeanModel<?> dataModel, String key) { String pageName = globals.getActivePageName(); BeanModel bm = get(pageName, dataModel.getBeanType(), key); if (bm == null) bm = get(pageName, dataModel.getBeanType(), defaultKey); if (bm == null) return false; String exclude = StringUtils.isNotEmpty(bm.exclude()) ? bm.exclude() : null; String include = StringUtils.isNotEmpty(bm.include()) ? bm.include() : null; String reorder = StringUtils.isNotEmpty(bm.reorder()) ? bm.reorder() : null; BeanModelUtils.modify(dataModel, null, include, exclude, reorder); return true; } private BeanModel get(String page, Class beanType, String key) { if (beanModels.containsKey(page)) { return get(beanModels.get(page), beanType, key); } return null; } private BeanModel get(Map<Class, Map<String, BeanModel>> beanModelsInPage, Class clazz, String key) { if (beanModelsInPage.containsKey(clazz)) { return beanModelsInPage.get(clazz).get(key); } return null; } public void put(String page, BeanModel bm) { Map<Class, Map<String, BeanModel>> map; if (beanModels.containsKey(page)) { map = beanModels.get(page); } else { map = new HashMap<Class, Map<String, BeanModel>>(); beanModels.put(page, map); } if (bm.pageType() != PageType.DEFAULT) logger.warn("{}@BeanModel.pageType value is ignored when the @BeanModel annotation is used on pages", page); if (bm.beanType() == void.class) throw new NullPointerException("@BeanModel.beanType is required when the @BeanModel annotation is used on pages"); put(map, bm); } private void put(Map<Class, Map<String, BeanModel>> beanModelsInPage, BeanModel bm) { Map<String, BeanModel> map; if (beanModelsInPage.containsKey(bm.beanType())) { map = beanModelsInPage.get(bm.beanType()); } else { map = new HashMap<String, BeanModel>(); beanModelsInPage.put(bm.beanType(), map); } map.put(getKey(bm.key()), bm); } private String getKey(String context) { return StringUtils.isNotEmpty(context) ? context : defaultKey; } /** * Clears the cache of models */ @Override public void objectWasInvalidated() { beanModels.clear(); } @PostInjection public void listenForInvalidations(@ComponentClasses InvalidationEventHub hub) { hub.addInvalidationListener(this); } }