package org.tynamo.pages;
import org.apache.commons.collections.CollectionUtils;
import org.apache.tapestry5.FieldTranslator;
import org.apache.tapestry5.FieldValidator;
import org.apache.tapestry5.SelectModel;
import org.apache.tapestry5.ValueEncoder;
import org.apache.tapestry5.annotations.Component;
import org.apache.tapestry5.annotations.Environmental;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.beaneditor.BeanModel;
import org.apache.tapestry5.corelib.components.Select;
import org.apache.tapestry5.corelib.components.TextArea;
import org.apache.tapestry5.corelib.components.TextField;
import org.apache.tapestry5.corelib.data.BlankOption;
import org.apache.tapestry5.internal.BeanValidationContext;
import org.apache.tapestry5.ioc.Messages;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.services.BeanEditContext;
import org.apache.tapestry5.services.BeanModelSource;
import org.apache.tapestry5.services.PropertyEditContext;
import org.apache.tapestry5.services.ValueEncoderSource;
import org.apache.tapestry5.util.EnumSelectModel;
import org.tynamo.components.EditComposition;
import org.tynamo.descriptor.CollectionDescriptor;
import org.tynamo.descriptor.IdentifierDescriptor;
import org.tynamo.descriptor.TynamoPropertyDescriptor;
import org.tynamo.services.DescriptorService;
import org.tynamo.services.PersistenceService;
import org.tynamo.util.GenericSelectionModel;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
/**
* A page that exists to contain blocks used to edit different types of properties. The blocks on this page are
* contributed into the {@link org.apache.tapestry5.services.BeanBlockSource} service configuration.
*
* @see org.apache.tapestry5.services.BeanBlockContribution
* @see org.apache.tapestry5.corelib.components.BeanEditForm
*/
public class PropertyEditBlocks
{
@Environmental
@Property(write = false)
private BeanEditContext beanEditContext;
@Environmental
@Property(write = false)
private PropertyEditContext propertyEditContext;
@Environmental
@Property(write = false)
private BeanValidationContext beanValidationContext;
@Inject
private PersistenceService persistenceService;
@Inject
private DescriptorService descriptorService;
@Inject
private ValueEncoderSource valueEncoderSource;
@Inject
private BeanModelSource beanModelSource;
@Inject
private Locale locale;
@Component(parameters = {"value=propertyEditContext.propertyValue", "label=prop:propertyEditContext.label",
"translate=prop:textFieldTranslator", "validate=prop:textFieldValidator",
"clientId=prop:propertyEditContext.propertyId", "annotationProvider=propertyEditContext"})
private TextField textField;
@Component(
parameters = {"value=propertyEditContext.propertyValue", "label=prop:propertyEditContext.label",
"translate=prop:textAreaTranslator", "validate=prop:textAreaValidator",
"clientId=prop:propertyEditContext.propertyId",
"annotationProvider=propertyEditContext"})
private TextArea textArea;
@Component(parameters = {"collection=propertyEditContext.propertyValue", "label=prop:propertyEditContext.label",
"clientId=prop:propertyEditContext.propertyId", "collectionDescriptor=propertyDescriptor",
"owner=beanValidationContext.beanInstance"})
private EditComposition editComposition;
@Component(parameters = {"model=beanValidationContext.beanInstance", "propertyDescriptor=propertyDescriptor"})
private org.tynamo.components.Blob blob;
@Component(
parameters = {"value=propertyEditContext.propertyValue", "label=prop:propertyEditContext.label",
"encoder=valueEncoderForProperty", "model=selectModelForProperty", "validate=prop:selectValidator",
"clientId=prop:propertyEditContext.propertyId", "blankOption=prop:blankOption"})
private Select select;
public TynamoPropertyDescriptor getPropertyDescriptor()
{
return descriptorService.getClassDescriptor(beanEditContext.getBeanClass()).getPropertyDescriptor(propertyEditContext.getPropertyId());
}
@SuppressWarnings({"unchecked"})
public SelectModel getSelectModelForProperty()
{
TynamoPropertyDescriptor propertyDescriptor = getPropertyDescriptor();
Class type = propertyDescriptor != null && propertyDescriptor.isCollection() ?
((CollectionDescriptor) propertyDescriptor).getElementType() : propertyEditContext.getPropertyType();
if (type.isEnum()) return new EnumSelectModel(type, getMessages());
if (propertyDescriptor != null && propertyDescriptor.isCollection() && ((CollectionDescriptor) propertyDescriptor).isOneToMany())
{
return new GenericSelectionModel(persistenceService.getOrphanInstances((CollectionDescriptor) propertyDescriptor, beanValidationContext.getBeanInstance()));
}
return new GenericSelectionModel(persistenceService.getInstances(type));
}
/**
* Provide a value encoder for a type.
*
* @return
*/
public ValueEncoder getValueEncoderForProperty()
{
TynamoPropertyDescriptor propertyDescriptor = getPropertyDescriptor();
if (propertyDescriptor != null && propertyDescriptor.isCollection())
{
CollectionDescriptor collectionDescriptor = (CollectionDescriptor) propertyDescriptor;
return valueEncoderSource.getValueEncoder(collectionDescriptor.getElementType());
}
return valueEncoderSource.getValueEncoder(propertyEditContext.getPropertyType());
}
public FieldTranslator getTextFieldTranslator()
{
return propertyEditContext.getTranslator(textField);
}
public FieldValidator getTextFieldValidator()
{
return propertyEditContext.getValidator(textField);
}
public FieldTranslator getTextAreaTranslator()
{
return propertyEditContext.getTranslator(textArea);
}
public FieldValidator getTextAreaValidator()
{
return propertyEditContext.getValidator(textArea);
}
public FieldValidator getSelectValidator()
{
return propertyEditContext.getValidator(select);
}
public boolean isPropertyValueInstanceOfList()
{
CollectionDescriptor descriptor = (CollectionDescriptor) getPropertyDescriptor();
return descriptor.getPropertyType().isAssignableFrom(List.class);
}
/**
* Palette's parameter "selected" only accepts java.util.List If the collection is a java.util.Set it needs to get
* converted
*/
public List getSelected()
{
Object value = propertyEditContext.getPropertyValue();
if (isPropertyValueInstanceOfList())
{
return value != null ? (List) value : new ArrayList();
} else
{
ArrayList selectedList = new ArrayList();
if (value != null) selectedList.addAll((Collection) value);
return selectedList;
}
}
public void setSelected(List selected)
{
Collection collection = (Collection) propertyEditContext.getPropertyValue();
if (collection != null) {
CollectionDescriptor descriptor = (CollectionDescriptor) getPropertyDescriptor();
for (Object o : CollectionUtils.subtract(selected, collection))
{
persistenceService.addToCollection(descriptor, o, beanValidationContext.getBeanInstance());
}
for (Object o : CollectionUtils.subtract(collection, selected))
{
persistenceService.removeFromCollection(descriptor, o, beanValidationContext.getBeanInstance());
}
} else {
if (isPropertyValueInstanceOfList()) {
propertyEditContext.setPropertyValue(selected);
} else {
Set set = new HashSet();
set.addAll(selected);
propertyEditContext.setPropertyValue(set);
}
}
}
public boolean isNotEditable()
{
IdentifierDescriptor descriptor = (IdentifierDescriptor) getPropertyDescriptor();
return descriptor.isGenerated() || propertyEditContext.getPropertyValue() != null;
}
public BeanModel getEmbeddedModel()
{
return beanModelSource.createEditModel(propertyEditContext.getPropertyType(), getMessages());
}
private Messages getMessages()
{
return propertyEditContext.getContainerMessages();
}
/**
* Looks for a help message within the messages based on the id.
*/
public String getHelpMessage()
{
Messages messages = getMessages();
String key = propertyEditContext.getPropertyId() + "-help";
if (messages.contains(key)) return messages.get(key);
return null;
}
public BlankOption getBlankOption()
{
return getPropertyDescriptor().isRequired() ? BlankOption.NEVER : BlankOption.ALWAYS;
}
}