001    package org.tynamo.components;
002    
003    import org.apache.tapestry5.Asset;
004    import org.apache.tapestry5.BindingConstants;
005    import org.apache.tapestry5.annotations.Parameter;
006    import org.apache.tapestry5.annotations.Property;
007    import org.apache.tapestry5.beaneditor.BeanModel;
008    import org.apache.tapestry5.ioc.Messages;
009    import org.apache.tapestry5.ioc.annotations.Inject;
010    import org.apache.tapestry5.ioc.services.PropertyAccess;
011    import org.apache.tapestry5.services.BeanModelSource;
012    import org.slf4j.Logger;
013    import org.tynamo.descriptor.CollectionDescriptor;
014    import org.tynamo.descriptor.TynamoClassDescriptor;
015    import org.tynamo.services.DescriptorService;
016    import org.tynamo.services.PersistenceService;
017    
018    import java.util.Collection;
019    import java.util.List;
020    
021    
022    /**
023     * This component produces a editor for a Composition (child collection).
024     * It allows a user to edit a collection property
025     */
026    public class EditComposition
027    {
028    
029            @Inject
030            private Logger logger;
031    
032            @Inject
033            private DescriptorService descriptorService;
034    
035            @Inject
036            private PersistenceService persitenceService;
037    
038            @Inject
039            private PropertyAccess propertyAccess;
040    
041            @Inject
042            private BeanModelSource beanModelSource;
043    
044            @Inject
045            private Messages messages;
046    
047            /**
048             * The id used to generate a page-unique client-side identifier for the component. If a component renders multiple
049             * times, a suffix will be appended to the to id to ensure uniqueness. The uniqued value may be accessed via the
050             * {@link #getClientId() clientId property}.
051             */
052            @Parameter(value = "prop:componentResources.id", defaultPrefix = BindingConstants.LITERAL)
053            @Property(write = false)
054            private String clientId;
055    
056            /**
057             * The user presentable label for the field. If not provided, a reasonable label is generated from the component's
058             * id, first by looking for a message key named "id-label" (substituting the component's actual id), then by
059             * converting the actual id to a presentable string (for example, "userId" to "User Id").
060             */
061            @Parameter(defaultPrefix = BindingConstants.LITERAL)
062            @Property(write = false)
063            private String label;
064    
065    
066            @Parameter(required = false)
067            private List instances;
068    
069            @Parameter(required = true)
070            @Property(write = false)
071            private Collection collection;
072    
073            /**
074             * The object which owns the collection being edited
075             */
076            @Parameter(required = false)
077            private Object owner;
078    
079            /**
080             * Ognl expression to invoke on the model to create a new child instance
081             */
082            @Parameter(required = false)
083            private String createExpression;
084    
085            /**
086             * @return The CollectionDescriptor for the collection being edited
087             */
088            @Parameter(required = true)
089            @Property(write = false)
090            private CollectionDescriptor collectionDescriptor;
091    
092            @Property
093            private Object collectionIterator;
094    
095            @Parameter(value = "true")
096            private boolean allowCreate;
097    
098            public boolean isAllowCreate()
099            {
100                    return propertyAccess.get(owner, descriptorService.getClassDescriptor(owner.getClass())
101                                    .getIdentifierDescriptor().getName()) != null;
102            }
103    
104            @Parameter(value = "prop:collectionDescriptor.allowRemove")
105            private boolean allowRemove;
106    
107            @Property
108            private int index;
109    
110            @Parameter(value = "asset:move_up.gif")
111            @Property(write = false)
112            private Asset upImage;
113    
114            @Parameter(value = "asset:move_down.gif")
115            @Property(write = false)
116            private Asset downImage;
117    
118            @Property(write = false)
119            private BeanModel beanModel;
120    
121            void setupRender()
122            {
123                    beanModel = beanModelSource.create(collectionDescriptor.getElementType(), false, messages);
124                    for (String propertyName : (List<String>) beanModel.getPropertyNames())
125                    {
126                            beanModel.get(propertyName).sortable(false);
127                    }
128            }
129    
130    /*      public void remove()
131            {
132                    int i = 0;
133                    // TODO CN - This code stinks (I wrote it).  Isn't there a better way??
134                    ArrayList deleting = new ArrayList();
135                    for (Object element : getCollection())
136                    {
137                            if (getSelected().get(i))
138                            {
139                                    deleting.add(element);
140                            }
141                            i++;
142                    }
143    
144                    for (Object element : deleting)
145                    {
146                            Utils.executeOgnlExpression(collectionDescriptor.getRemoveExpression(), element, owner);
147                            persitenceService.remove(element);
148                    }
149            }
150    
151            public boolean isList()
152            {
153                    return collection instanceof List;
154            }
155    
156            public void moveUp()
157            {
158                    List list = (List) collection;
159                    for (int i = 1; i < getSelected().size(); i++)
160                    {
161                            if (getSelected().get(i))
162                            {
163                                    if (collectionDescriptor.getSwapExpression() == null)
164                                    {
165                                            Collections.swap(list, i, i - 1);
166                                    } else
167                                    {
168                                            try
169                                            {
170                                                    Ognl.getValue(collectionDescriptor.getSwapExpression() + "(" + i + "," + (i - 1) + ")", owner);
171                                            } catch (OgnlException e)
172                                            {
173                                                    LOGGER.error(e.getMessage());
174                                            }
175                                    }
176                            }
177                    }
178            }
179    
180            public void moveDown()
181            {
182                    List list = (List) collection;
183                    for (int i = 0; i < getSelected().size() - 1; i++)
184                    {
185                            if (collectionDescriptor.getSwapExpression() == null)
186                            {
187                                    Collections.swap(list, i, i + 1);
188                            } else
189                            {
190                                    try
191                                    {
192                                            Ognl.getValue(collectionDescriptor.getSwapExpression() + "(" + i + "," + (i + 1) + ")",
193                                                            owner);
194                                    } catch (OgnlException e)
195                                    {
196                                            LOG.error(e.getMessage());
197                                    }
198                            }
199                    }
200            }*/
201    
202            public Object[] getEditCompositionPageContext()
203            {
204                    return new Object[]{collectionDescriptor.getBeanType(), owner, collectionDescriptor.getName(), collectionIterator};
205            }
206    
207            public Object[] getAddCompositionPageContext()
208            {
209                    return new Object[]{collectionDescriptor.getBeanType(), owner, collectionDescriptor.getName()};
210            }
211    
212    
213            public final String getModelId()
214            {
215                    TynamoClassDescriptor classDescriptor = 
216                                    descriptorService.getClassDescriptor(collectionDescriptor.getBeanType());
217                    return propertyAccess.get(collectionIterator, classDescriptor.getIdentifierDescriptor().getName()).toString();
218            }
219    }