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    }