package org.tynamo.mixins;
import org.apache.commons.lang.StringUtils;
import org.apache.tapestry5.BindingConstants;
import org.apache.tapestry5.annotations.CleanupRender;
import org.apache.tapestry5.annotations.InjectContainer;
import org.apache.tapestry5.annotations.Log;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.annotations.SetupRender;
import org.apache.tapestry5.corelib.components.BeanDisplay;
import org.apache.tapestry5.corelib.components.BeanEditForm;
import org.apache.tapestry5.corelib.components.BeanEditor;
import org.apache.tapestry5.corelib.components.Grid;
import org.apache.tapestry5.corelib.components.PropertyDisplay;
import org.apache.tapestry5.corelib.components.PropertyEditor;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.services.PropertyAccess;
import org.apache.tapestry5.services.Environment;
import org.tynamo.PageType;
import org.tynamo.services.BeanModelSourceContext;
import org.tynamo.services.TynamoBeanContext;
/**
* This mixin has two purposes.
* <p/>
* it pushes the {@link TynamoBeanContext} into the {@link Environment} it's meant to be used in a {@link BeanDisplay} or with a {@link Grid}
* it pushes the {@link BeanModelSourceContext} into the {@link Environment}
*/
public class BeanModelAdvisor
{
/**
* The component to which this mixin is attached.
*/
@InjectContainer
private Object container;
@Inject
private Environment environment;
@Inject
private PropertyAccess propertyAccess;
/**
* The context key
*/
@Parameter(defaultPrefix = BindingConstants.LITERAL, allowNull = false, value = "prop:guessKey()")
private String key;
/**
* The container's property to retrieve the object (or bean)
*/
@Parameter(defaultPrefix = BindingConstants.LITERAL, allowNull = false)
private String containerProperty;
@Log
@SetupRender
void setup()
{
pushBeanModelSourceContext();
if (isTynamoBeanContextNeeded()) pushTynamoBeanContext();
}
private void pushBeanModelSourceContext()
{
BeanModelSourceContext context = new BeanModelSourceContext(key);
environment.push(BeanModelSourceContext.class, context);
}
private void pushTynamoBeanContext()
{
if (StringUtils.isEmpty(containerProperty)) containerProperty = guessPropertyName();
TynamoBeanContext context = new TynamoBeanContext()
{
public Class getBeanType()
{
return getObject().getClass();
}
public Object getBeanInstance()
{
return getObject();
}
public String getCurrentProperty()
{
return null;
}
public void setCurrentProperty(String s)
{
}
private Object getObject()
{
return propertyAccess.get(container, containerProperty);
}
};
environment.push(TynamoBeanContext.class, context);
}
public String guessKey()
{
if (container instanceof Grid) return PageType.LIST.getContextKey();
if (container instanceof BeanDisplay || container instanceof PropertyDisplay)
{
return PageType.SHOW.getContextKey();
}
if (container instanceof BeanEditor || container instanceof BeanEditForm || container instanceof PropertyEditor)
{
return PageType.EDIT.getContextKey();
}
throw new RuntimeException(
"The context key couldn't be guessed from the container, please provide one. eg: beanModelAdvisor.key=\"add\"");
}
private String guessPropertyName()
{
if (container instanceof Grid) return "row";
if (container instanceof BeanDisplay) return "object";
throw new RuntimeException(
"The container's object property couldn't be guessed, please provide one. eg: beanModelAdvisor.containerProperty=\"bean\"");
}
private boolean isTynamoBeanContextNeeded()
{
return containerProperty != null || (container instanceof Grid) || (container instanceof BeanDisplay);
}
@Log
@CleanupRender
void cleanup()
{
environment.pop(BeanModelSourceContext.class);
if (isTynamoBeanContextNeeded()) environment.pop(TynamoBeanContext.class);
}
}