001    package org.tynamo.pages;
002    
003    import org.apache.commons.collections.CollectionUtils;
004    import org.apache.tapestry5.*;
005    import org.apache.tapestry5.annotations.Component;
006    import org.apache.tapestry5.annotations.Environmental;
007    import org.apache.tapestry5.annotations.Property;
008    import org.apache.tapestry5.beaneditor.BeanModel;
009    import org.apache.tapestry5.corelib.components.Select;
010    import org.apache.tapestry5.corelib.components.TextField;
011    import org.apache.tapestry5.corelib.data.BlankOption;
012    import org.apache.tapestry5.internal.BeanValidationContext;
013    import org.apache.tapestry5.ioc.Messages;
014    import org.apache.tapestry5.ioc.annotations.Inject;
015    import org.apache.tapestry5.services.BeanEditContext;
016    import org.apache.tapestry5.services.BeanModelSource;
017    import org.apache.tapestry5.services.PropertyEditContext;
018    import org.apache.tapestry5.services.ValueEncoderSource;
019    import org.apache.tapestry5.util.EnumSelectModel;
020    import org.tynamo.components.EditComposition;
021    import org.tynamo.descriptor.CollectionDescriptor;
022    import org.tynamo.descriptor.IdentifierDescriptor;
023    import org.tynamo.descriptor.TynamoPropertyDescriptor;
024    import org.tynamo.services.DescriptorService;
025    import org.tynamo.services.PersistenceService;
026    import org.tynamo.util.GenericSelectionModel;
027    
028    import java.util.ArrayList;
029    import java.util.Collection;
030    import java.util.List;
031    
032    /**
033     * A page that exists to contain blocks used to edit different types of properties. The blocks on this page are
034     * contributed into the {@link org.apache.tapestry5.services.BeanBlockSource} service configuration.
035     *
036     * @see org.apache.tapestry5.services.BeanBlockContribution
037     * @see org.apache.tapestry5.corelib.components.BeanEditForm
038     */
039    public class PropertyEditBlocks
040    {
041    
042            @Environmental
043            @Property(write = false)
044            private BeanEditContext beanEditContext;
045    
046            @Environmental
047            @Property(write = false)
048            private PropertyEditContext propertyEditContext;
049    
050            @Environmental
051            @Property(write = false)
052            private BeanValidationContext tynamoBeanContext;
053    
054            @Inject
055            private PersistenceService persistenceService;
056    
057            @Inject
058            private DescriptorService descriptorService;
059    
060            @Inject
061            private ValueEncoderSource valueEncoderSource;
062    
063            @Inject
064            private BeanModelSource beanModelSource;
065    
066            @Component(parameters = {"value=propertyEditContext.propertyValue", "label=prop:propertyEditContext.label",
067                            "translate=prop:textFieldTranslator", "validate=prop:textFieldValidator",
068                            "clientId=prop:propertyEditContext.propertyId", "annotationProvider=propertyEditContext"})
069            private TextField textField;
070    
071            @Component(parameters = {"collection=propertyEditContext.propertyValue", "label=prop:propertyEditContext.label",
072                            "clientId=prop:propertyEditContext.propertyId", "collectionDescriptor=propertyDescriptor",
073                            "owner=tynamoBeanContext.beanInstance"})
074            private EditComposition editComposition;
075    
076            @Component(parameters = {"model=tynamoBeanContext.beanInstance", "propertyDescriptor=propertyDescriptor"})
077            private org.tynamo.components.Blob blob;
078    
079            @Component(
080                            parameters = {"value=propertyEditContext.propertyValue", "label=prop:propertyEditContext.label",
081                                            "encoder=valueEncoderForProperty", "model=selectModelForProperty", "validate=prop:selectValidator",
082                                            "clientId=prop:propertyEditContext.propertyId", "blankOption=prop:blankOption"})
083            private Select select;
084    
085            public TynamoPropertyDescriptor getPropertyDescriptor()
086            {
087                    return descriptorService.getClassDescriptor(beanEditContext.getBeanClass()).getPropertyDescriptor(propertyEditContext.getPropertyId());
088            }
089    
090            @SuppressWarnings({"unchecked"})
091            public SelectModel getSelectModelForProperty()
092            {
093                    TynamoPropertyDescriptor propertyDescriptor = getPropertyDescriptor();
094    
095                    Class type = propertyDescriptor.isCollection() ? ((CollectionDescriptor) propertyDescriptor).getElementType() : propertyDescriptor.getPropertyType();
096                    if (type.isEnum()) return new EnumSelectModel(type, getMessages());
097    
098                    if (propertyDescriptor.isCollection() && ((CollectionDescriptor) propertyDescriptor).isOneToMany())
099                    {
100                            return new GenericSelectionModel(persistenceService.getOrphanInstances((CollectionDescriptor) propertyDescriptor, tynamoBeanContext.getBeanInstance()));
101                    }
102    
103                    return new GenericSelectionModel(persistenceService.getInstances(type));
104            }
105    
106            /**
107             * Provide a value encoder for a type.
108             *
109             * @return
110             */
111            public ValueEncoder getValueEncoderForProperty()
112            {
113                    TynamoPropertyDescriptor propertyDescriptor = getPropertyDescriptor();
114                    if (propertyDescriptor.isCollection())
115                    {
116                            CollectionDescriptor collectionDescriptor = (CollectionDescriptor) propertyDescriptor;
117                            return valueEncoderSource.getValueEncoder(collectionDescriptor.getElementType());
118                    } else
119                    {
120                            return valueEncoderSource.getValueEncoder(propertyEditContext.getPropertyType());
121                    }
122            }
123    
124            public FieldTranslator getTextFieldTranslator()
125            {
126                    return propertyEditContext.getTranslator(textField);
127            }
128    
129            public FieldValidator getTextFieldValidator()
130            {
131                    return propertyEditContext.getValidator(textField);
132            }
133    
134            public FieldValidator getSelectValidator()
135            {
136                    return propertyEditContext.getValidator(select);
137            }
138    
139            public boolean isPropertyValueInstanceOfList()
140            {
141                    return propertyEditContext.getPropertyValue() instanceof List;
142            }
143    
144            /**
145             * Palette's parameter "selected" only accepts java.util.List If the collection is a java.util.Set it needs to get
146             * converted
147             */
148            public List getSelected()
149            {
150                    if (isPropertyValueInstanceOfList())
151                    {
152                            return (List) propertyEditContext.getPropertyValue();
153                    } else
154                    {
155                            ArrayList selectedList = new ArrayList();
156                            selectedList.addAll((Collection) propertyEditContext.getPropertyValue());
157                            return selectedList;
158                    }
159            }
160    
161            public void setSelected(List selected)
162            {
163                    Collection collection = (Collection) propertyEditContext.getPropertyValue();
164                    CollectionDescriptor descriptor = (CollectionDescriptor) getPropertyDescriptor();
165    
166                    for (Object o : CollectionUtils.subtract(selected, collection))
167                    {
168                            persistenceService.addToCollection(descriptor, o, tynamoBeanContext.getBeanInstance());
169                    }
170    
171                    for (Object o : CollectionUtils.subtract(collection, selected))
172                    {
173                            persistenceService.removeFromCollection(descriptor, o, tynamoBeanContext.getBeanInstance());
174                    }
175    
176            }
177    
178            public boolean isNotEditable()
179            {
180                    IdentifierDescriptor descriptor = (IdentifierDescriptor) getPropertyDescriptor();
181                    return descriptor.isGenerated() || propertyEditContext.getPropertyValue() != null;
182            }
183    
184            public BeanModel getEmbeddedModel()
185            {
186                    return beanModelSource.createEditModel(propertyEditContext.getPropertyType(), getMessages());
187            }
188    
189            private Messages getMessages()
190            {
191                    return propertyEditContext.getContainerMessages();
192            }
193    
194            /**
195             * Looks for a help message within the messages based on the id.
196             */
197            public String getHelpMessage()
198            {
199                    Messages messages = getMessages();
200                    String key = propertyEditContext.getPropertyId() + "-help";
201                    if (messages.contains(key)) return messages.get(key);
202                    return null;
203            }
204    
205            public BlankOption getBlankOption()
206            {
207                    return getPropertyDescriptor().isRequired() ? BlankOption.NEVER : BlankOption.ALWAYS;
208            }
209    
210    }