| Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
| BaseListPage |
|
| 0.0;0 |
| 1 | // Copyright 2008 Thiago H. de Paula Figueiredo | |
| 2 | // | |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); | |
| 4 | // you may not use this file except in compliance with the License. | |
| 5 | // You may obtain a copy of the License at | |
| 6 | // | |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 | |
| 8 | // | |
| 9 | // Unless required by applicable law or agreed to in writing, software | |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, | |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 12 | // See the License for the specific language governing permissions and | |
| 13 | // limitations under the License. | |
| 14 | ||
| 15 | package br.com.arsmachina.tapestrycrud.base; | |
| 16 | ||
| 17 | import java.io.Serializable; | |
| 18 | ||
| 19 | import org.apache.tapestry5.ComponentResources; | |
| 20 | import org.apache.tapestry5.EventContext; | |
| 21 | import org.apache.tapestry5.PrimaryKeyEncoder; | |
| 22 | import org.apache.tapestry5.annotations.Cached; | |
| 23 | import org.apache.tapestry5.annotations.OnEvent; | |
| 24 | import org.apache.tapestry5.annotations.PageDetached; | |
| 25 | import org.apache.tapestry5.annotations.Retain; | |
| 26 | import org.apache.tapestry5.beaneditor.BeanModel; | |
| 27 | import org.apache.tapestry5.corelib.components.Grid; | |
| 28 | import org.apache.tapestry5.ioc.annotations.Inject; | |
| 29 | import org.apache.tapestry5.services.BeanModelSource; | |
| 30 | import org.apache.tapestry5.services.Request; | |
| 31 | ||
| 32 | import br.com.arsmachina.tapestrycrud.Constants; | |
| 33 | import br.com.arsmachina.tapestrycrud.grid.ControllerGridDataSource; | |
| 34 | import br.com.arsmachina.tapestrycrud.services.PrimaryKeyEncoderSource; | |
| 35 | ||
| 36 | /** | |
| 37 | * Base class for pages that list entity objects. The <code>object</code> property is meant to be | |
| 38 | * used as the <code>row</code> parameter of the {@link Grid} component. | |
| 39 | * | |
| 40 | * One example of its use can be found in the Ars Machina Project Example Application (<a | |
| 41 | * href="http://ars-machina.svn.sourceforge.net/viewvc/ars-machina/example/trunk/src/main/java/br/com/arsmachina/example/web/pages/project/ListProject.java?view=markup" | |
| 42 | * >page class</a>. <a | |
| 43 | * href="http://ars-machina.svn.sourceforge.net/viewvc/ars-machina/example/trunk/src/main/webapp/project/ListProject.tml?view=markup" | |
| 44 | * >template</a>). | |
| 45 | * | |
| 46 | * | |
| 47 | * @param <T> the entity class related to this encoder. | |
| 48 | * @param <K> the type of the class' primary key property. | |
| 49 | * | |
| 50 | * @author Thiago H. de Paula Figueiredo | |
| 51 | */ | |
| 52 | public abstract class BaseListPage<T, K extends Serializable> extends BasePage<T, K> { | |
| 53 | ||
| 54 | @Inject | |
| 55 | private ComponentResources componentResources; | |
| 56 | ||
| 57 | @Inject | |
| 58 | private Request request; | |
| 59 | ||
| 60 | @Inject | |
| 61 | private PrimaryKeyEncoderSource primaryKeyEncoderSource; | |
| 62 | ||
| 63 | @Retain | |
| 64 | private PrimaryKeyEncoder<K, T> primaryKeyEncoder; | |
| 65 | ||
| 66 | @Inject | |
| 67 | private BeanModelSource beanModelSource; | |
| 68 | ||
| 69 | private T object; | |
| 70 | ||
| 71 | /** | |
| 72 | * Single constructor of this class. | |
| 73 | */ | |
| 74 | @SuppressWarnings("unchecked") | |
| 75 | public BaseListPage() { | |
| 76 | ||
| 77 | 0 | super(); |
| 78 | ||
| 79 | 0 | primaryKeyEncoder = (PrimaryKeyEncoder<K, T>) primaryKeyEncoderSource.get(getEntityClass()); |
| 80 | ||
| 81 | 0 | } |
| 82 | ||
| 83 | /** | |
| 84 | * Method used as the <code>source</code> parameter of the {@link Grid} component. This | |
| 85 | * implementation returns <code>new {@link ControllerGridDataSource}(getController())</code>. | |
| 86 | * | |
| 87 | * @return an {@link Object}. | |
| 88 | */ | |
| 89 | @SuppressWarnings("unchecked") | |
| 90 | @Cached | |
| 91 | public Object getObjects() { | |
| 92 | 0 | return new ControllerGridDataSource(getEntityClass(), getController()); |
| 93 | } | |
| 94 | ||
| 95 | /** | |
| 96 | * Returns the value of the <code>object</code> property. | |
| 97 | * | |
| 98 | * @return a {@link T}. | |
| 99 | */ | |
| 100 | public T getObject() { | |
| 101 | 0 | return object; |
| 102 | } | |
| 103 | ||
| 104 | /** | |
| 105 | * Changes the value of the <code>object</code> property. | |
| 106 | * | |
| 107 | * @param object a {@link T}. | |
| 108 | */ | |
| 109 | public void setObject(T object) { | |
| 110 | 0 | this.object = object; |
| 111 | 0 | } |
| 112 | ||
| 113 | /** | |
| 114 | * Adds an <code>action</code> property to the {@link BeanModel}. | |
| 115 | * | |
| 116 | * @see br.com.arsmachina.tapestrycrud.base.BasePage#getBeanModel() | |
| 117 | */ | |
| 118 | @SuppressWarnings("unchecked") | |
| 119 | public BeanModel<T> getBeanModel() { | |
| 120 | ||
| 121 | 0 | final BeanModel<T> beanModel = beanModelSource.createDisplayModel(getEntityClass(), |
| 122 | 0 | getMessages()); |
| 123 | 0 | beanModel.add(Constants.ACTION_PROPERTY_NAME, null); |
| 124 | ||
| 125 | 0 | return beanModel; |
| 126 | ||
| 127 | } | |
| 128 | ||
| 129 | /** | |
| 130 | * Removes or not a given object. This method only removes an object, using | |
| 131 | * <code>getController().delete(id)</code>, if {@link canRemove(K)} returns <code>true</code>. | |
| 132 | * | |
| 133 | * @param object a {@link K}. | |
| 134 | */ | |
| 135 | protected final Object remove(T object) { | |
| 136 | ||
| 137 | 0 | if (object == null) { |
| 138 | 0 | setRemoveErrorNotFoundMessage(); |
| 139 | } | |
| 140 | ||
| 141 | 0 | else if (canRemove(object)) { |
| 142 | ||
| 143 | 0 | getController().delete(object); |
| 144 | 0 | setRemoveSuccessMessage(); |
| 145 | ||
| 146 | } | |
| 147 | else { | |
| 148 | 0 | setRemoveErrorNotAllowedMessage(); |
| 149 | } | |
| 150 | ||
| 151 | 0 | return returnFromDoRemove(); |
| 152 | ||
| 153 | } | |
| 154 | ||
| 155 | /** | |
| 156 | * Defines what {@link #doRemove()} will return. | |
| 157 | * | |
| 158 | * @return an {@link Object} or <code>null</code>. | |
| 159 | */ | |
| 160 | protected Object returnFromDoRemove() { | |
| 161 | ||
| 162 | 0 | Object returnValue = null; |
| 163 | ||
| 164 | 0 | if (request.isXHR()) { |
| 165 | ||
| 166 | 0 | if (returnZoneOnXHR()) { |
| 167 | 0 | returnValue = getFormZone(); |
| 168 | } | |
| 169 | else { | |
| 170 | 0 | returnValue = componentResources.getBlock(getFormBlockId()); |
| 171 | } | |
| 172 | ||
| 173 | } | |
| 174 | ||
| 175 | 0 | return returnValue; |
| 176 | ||
| 177 | } | |
| 178 | ||
| 179 | /** | |
| 180 | * Sets the remove success message in this page. | |
| 181 | */ | |
| 182 | protected void setRemoveSuccessMessage() { | |
| 183 | 0 | setMessage(getMessages().get(Constants.MESSAGE_SUCCESS_REMOVE)); |
| 184 | 0 | } |
| 185 | ||
| 186 | /** | |
| 187 | * Sets the remove not done because of lack of priviledge message in this page. | |
| 188 | */ | |
| 189 | protected void setRemoveErrorNotAllowedMessage() { | |
| 190 | 0 | setMessage(getMessages().get(Constants.MESSAGE_ERROR_REMOVE_NOT_ALLOWED)); |
| 191 | 0 | } |
| 192 | ||
| 193 | /** | |
| 194 | * Sets the remove not done because object not found in this page. | |
| 195 | */ | |
| 196 | protected void setRemoveErrorNotFoundMessage() { | |
| 197 | 0 | setMessage(getMessages().get(Constants.MESSAGE_ERROR_REMOVE_NOT_FOUND)); |
| 198 | 0 | } |
| 199 | ||
| 200 | /** | |
| 201 | * Tells if a given object can be removed in this context. It must be overriden if you have some | |
| 202 | * rules about when an object can be removed. This implementation just returns <code>true</code>. | |
| 203 | * | |
| 204 | * @param object a {@link #T}. | |
| 205 | * @return a <code>boolean</code>. | |
| 206 | */ | |
| 207 | protected boolean canRemove(T object) { | |
| 208 | 0 | return true; |
| 209 | } | |
| 210 | ||
| 211 | /** | |
| 212 | * Clears the message after it is shown, preventing the message from appearing twice in AJAX | |
| 213 | * actions. | |
| 214 | */ | |
| 215 | @PageDetached | |
| 216 | void clearMessage() { | |
| 217 | ||
| 218 | 0 | if (request.isXHR()) { |
| 219 | 0 | setMessage(null); |
| 220 | } | |
| 221 | ||
| 222 | 0 | } |
| 223 | ||
| 224 | /** | |
| 225 | * This method listens to the {@link Constants#REMOVE_OBJECT_ACTION} event and removes the | |
| 226 | * corresponding object. | |
| 227 | * | |
| 228 | * @param context an {@link EventContext}. | |
| 229 | */ | |
| 230 | @OnEvent(Constants.REMOVE_OBJECT_ACTION) | |
| 231 | protected Object remove(EventContext context) { | |
| 232 | ||
| 233 | 0 | K id = context.get(getPrimaryKeyClass(), 0); |
| 234 | 0 | final T toBeRemoved = primaryKeyEncoder.toValue(id); |
| 235 | 0 | return remove(toBeRemoved); |
| 236 | ||
| 237 | } | |
| 238 | ||
| 239 | /** | |
| 240 | * Returns the configured {@link PrimaryKeyEncoder} for a given entity class. | |
| 241 | * | |
| 242 | * @param <X> the type of the entity. | |
| 243 | * @param clasz a {@link Class}. | |
| 244 | * @return a {@link PrimaryKeyEncoder}. | |
| 245 | * @see br.com.arsmachina.tapestrycrud.services.PrimaryKeyEncoderSource#get(java.lang.Class) | |
| 246 | */ | |
| 247 | protected <X, Y extends Serializable> PrimaryKeyEncoder<Y, X> getPrimaryKeyEncoder(Class<X> clasz) { | |
| 248 | 0 | return primaryKeyEncoderSource.get(clasz); |
| 249 | } | |
| 250 | ||
| 251 | } |