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 }