001 // Copyright 2008 Thiago H. de Paula Figueiredo
002 //
003 // Licensed under the Apache License, Version 2.0 (the "License");
004 // you may not use this file except in compliance with the License.
005 // You may obtain a copy of the License at
006 //
007 // http://www.apache.org/licenses/LICENSE-2.0
008 //
009 // Unless required by applicable law or agreed to in writing, software
010 // distributed under the License is distributed on an "AS IS" BASIS,
011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012 // See the License for the specific language governing permissions and
013 // limitations under the License.
014
015 package br.com.arsmachina.tapestrycrud.base;
016
017 import java.io.Serializable;
018 import java.lang.reflect.ParameterizedType;
019 import java.lang.reflect.Type;
020
021 import org.apache.tapestry5.Block;
022 import org.apache.tapestry5.ComponentResources;
023 import org.apache.tapestry5.PersistenceConstants;
024 import org.apache.tapestry5.PrimaryKeyEncoder;
025 import org.apache.tapestry5.ValueEncoder;
026 import org.apache.tapestry5.annotations.Persist;
027 import org.apache.tapestry5.annotations.Retain;
028 import org.apache.tapestry5.corelib.components.Zone;
029 import org.apache.tapestry5.ioc.Messages;
030 import org.apache.tapestry5.ioc.annotations.Inject;
031 import org.apache.tapestry5.services.ValueEncoderSource;
032
033 import br.com.arsmachina.controller.Controller;
034 import br.com.arsmachina.tapestrycrud.Constants;
035 import br.com.arsmachina.tapestrycrud.CrudPage;
036 import br.com.arsmachina.tapestrycrud.encoder.ActivationContextEncoder;
037 import br.com.arsmachina.tapestrycrud.encoder.LabelEncoder;
038 import br.com.arsmachina.tapestrycrud.selectmodel.SelectModelFactory;
039 import br.com.arsmachina.tapestrycrud.services.ActivationContextEncoderSource;
040 import br.com.arsmachina.module.service.ControllerSource;
041 import br.com.arsmachina.tapestrycrud.services.LabelEncoderSource;
042 import br.com.arsmachina.tapestrycrud.services.PrimaryKeyEncoderSource;
043 import br.com.arsmachina.tapestrycrud.services.PrimaryKeyTypeService;
044
045 /**
046 * Class that implements some common infrastructure for listing and editing pages. This class is not
047 *
048 * @author Thiago H. de Paula Figueiredo
049 * @param <T> the entity class related to this encoder.
050 * @param <K> the type of the class' primary key property.
051 */
052 public abstract class BasePage<T, K extends Serializable> implements CrudPage<T, K> {
053
054 @Inject
055 private ActivationContextEncoderSource activationContextEncoderSource;
056
057 @Inject
058 private ControllerSource controllerSource;
059
060 @Inject
061 private LabelEncoderSource labelEncoderSource;
062
063 @Inject
064 private ValueEncoderSource valueEncoderSource;
065
066 @Inject
067 private SelectModelFactory selectModelFactory;
068
069 @Inject
070 private PrimaryKeyEncoderSource primaryKeyEncoderSource;
071
072 @Inject
073 private PrimaryKeyTypeService primaryKeyTypeService;
074
075 @Retain
076 private Class<T> entityClass;
077
078 @Retain
079 private Controller<T, K> controller;
080
081 @Persist(PersistenceConstants.FLASH)
082 private String message;
083
084 @Inject
085 private ComponentResources componentResources;
086
087 @Inject
088 private Messages messages;
089
090 @Retain
091 private Class<K> primaryKeyClass;
092
093 /**
094 * Single constructor of this class.
095 */
096 @SuppressWarnings("unchecked")
097 public BasePage() {
098
099 final Type genericSuperclass = getClass().getGenericSuperclass();
100 final ParameterizedType parameterizedType = ((ParameterizedType) genericSuperclass);
101 entityClass = (Class<T>) parameterizedType.getActualTypeArguments()[0];
102 primaryKeyClass = primaryKeyTypeService.getPrimaryKeyType(entityClass);
103
104 controller = controllerSource.get(entityClass);
105
106 assert entityClass != null;
107 assert primaryKeyClass != null;
108 assert controller != null;
109
110 }
111
112 // /**
113 // * Creates a {@link BeanModel} for this entity class using
114 // * <code>beanModelSource.create(entityClass, false, componentResources)</code>. This method
115 // * can ve overriden if needed.
116 // *
117 // * @return a {@link BeanModel}.
118 // */
119 // public BeanModel<T> getBeanModel() {
120 // return beanModelSource.create(entityClass, filterReadOnlyComponentsInBeanModel(),
121 // getMessages());
122 // }
123
124 /**
125 * Used by {@link #getBeanModel()} to filter read only components or not. This implementation
126 * returns <code>true</code>.
127 *
128 * @return a <code>boolean</code>.
129 */
130 protected boolean filterReadOnlyComponentsInBeanModel() {
131 return true;
132 }
133
134 /**
135 * Returns the {@link ValueEncoder} for a given class.
136 *
137 * @param <V> the class.
138 * @param clasz a {@link Class};
139 * @return a {@link ValueEncoder}.
140 */
141 protected <V> ValueEncoder<V> getValueEncoder(Class<V> clasz) {
142 return valueEncoderSource.getValueEncoder(clasz);
143 }
144
145 /**
146 * Returns the {@link LabelEncoder} for a given class.
147 *
148 * @param <V> the class.
149 * @param clasz a {@link Class};
150 * @return a {@link LabelEncoder}.
151 */
152 protected <V> LabelEncoder<V> getLabelEncoder(Class<V> clasz) {
153 return labelEncoderSource.get(clasz);
154 }
155
156 /**
157 * Returns the {@link ActivationContextEncoder} for a given class.
158 *
159 * @param <V> the class.
160 * @param clasz a {@link Class};
161 * @return an {@link ActivationContextEncoder}.
162 */
163 protected <V, X extends Serializable> ActivationContextEncoder<V> getActivationContextEncoder(
164 Class<V> clasz) {
165 return activationContextEncoderSource.get(clasz);
166 }
167
168 /**
169 * Returns the {@link PrimaryKeyEncoder} for a given class.
170 *
171 * @param <V> the class.
172 * @param <X> the class' primary key field type.
173 * @param clasz a {@link Class};
174 * @return a {@link PrimaryKeyEncoder}.
175 */
176 protected <V, X extends Serializable> PrimaryKeyEncoder<X, V> getPrimaryKeyEncoder(
177 Class<V> clasz) {
178 return primaryKeyEncoderSource.get(clasz);
179 }
180
181 /**
182 * @see br.com.arsmachina.tapestrycrud.CrudPage#getMessage()
183 */
184 public String getMessage() {
185 return message;
186 }
187
188 /**
189 * @see br.com.arsmachina.tapestrycrud.CrudPage#setMessage(java.lang.String)
190 */
191 public void setMessage(String message) {
192 this.message = message;
193 }
194
195 /**
196 * Returns the value of the <code>controller</code> property.
197 *
198 * @return a {@link Controller<T,K>}.
199 */
200 public final Controller<T, K> getController() {
201 return controller;
202 }
203
204 public final Class<T> getEntityClass() {
205 return entityClass;
206 }
207
208 public final Class<K> getPrimaryKeyClass() {
209 return primaryKeyClass;
210 }
211
212 /**
213 * Returns the value of the <code>messages</code> property.
214 *
215 * @return a {@link Messages}.
216 */
217 public final Messages getMessages() {
218 return messages;
219 }
220
221 /**
222 * Returns the {@link Zone} that surrounds the form.
223 *
224 * @return a {@link Zone}.
225 */
226 public Zone getFormZone() {
227 return (Zone) componentResources.getEmbeddedComponent(getFormZoneId());
228 }
229
230 /**
231 * ID of the {@link Block} that will be returned when a form is submitted via AJAX. This
232 * implementation returns {@link #DEFAULT_FORM_BLOCK_ID} (<code>block</code>).
233 *
234 * @return a {@link String}.
235 */
236 String getFormBlockId() {
237 return Constants.DEFAULT_FORM_BLOCK_ID;
238 }
239
240 /**
241 * ID of the {@link Zone} that will be returned when a form is submitted via AJAX. This
242 * implementation returns {@link #DEFAULT_FORM_ZONE_ID} (<code>zone</code>).
243 *
244 * @return a {@link String}.
245 */
246 String getFormZoneId() {
247 return Constants.DEFAULT_FORM_ZONE_ID;
248 }
249
250 /**
251 * Used by {@link #returnFromRemove()} to know whether it must return a {@link Zone} or a
252 * {@link Block}. This implementation returns <code>true</code>.
253 *
254 * @return a <code>boolean</code>.
255 */
256 protected boolean returnZoneOnXHR() {
257 return true;
258 }
259
260 /**
261 * Returns the value of the <code>selectModelFactory</code> property.
262 *
263 * @return a {@link SelectModelFactory}.
264 */
265 final protected SelectModelFactory getSelectModelFactory() {
266 return selectModelFactory;
267 }
268
269 }