1 24 package org.riotfamily.riot.list.ui; 25 26 import java.io.PrintWriter ; 27 import java.io.StringWriter ; 28 import java.util.ArrayList ; 29 import java.util.Collection ; 30 import java.util.Collections ; 31 import java.util.HashMap ; 32 import java.util.Iterator ; 33 import java.util.List ; 34 import java.util.Map ; 35 36 import javax.servlet.http.HttpServletRequest ; 37 import javax.servlet.http.HttpServletResponse ; 38 39 import org.riotfamily.common.beans.PropertyUtils; 40 import org.riotfamily.common.beans.ProtectedBeanWrapper; 41 import org.riotfamily.common.i18n.MessageResolver; 42 import org.riotfamily.common.util.FormatUtils; 43 import org.riotfamily.common.util.ResourceUtils; 44 import org.riotfamily.forms.Element; 45 import org.riotfamily.forms.Form; 46 import org.riotfamily.forms.controller.FormContextFactory; 47 import org.riotfamily.forms.element.TextField; 48 import org.riotfamily.forms.factory.FormRepository; 49 import org.riotfamily.forms.request.SimpleFormRequest; 50 import org.riotfamily.riot.dao.SortableDao; 51 import org.riotfamily.riot.editor.EditorDefinition; 52 import org.riotfamily.riot.editor.EditorDefinitionUtils; 53 import org.riotfamily.riot.editor.ListDefinition; 54 import org.riotfamily.riot.editor.TreeDefinition; 55 import org.riotfamily.riot.list.ColumnConfig; 56 import org.riotfamily.riot.list.ListConfig; 57 import org.riotfamily.riot.list.command.Command; 58 import org.riotfamily.riot.list.command.CommandResult; 59 import org.riotfamily.riot.list.command.CommandState; 60 import org.riotfamily.riot.list.command.core.ChooseCommand; 61 import org.riotfamily.riot.list.command.core.DescendCommand; 62 import org.riotfamily.riot.list.command.result.ConfirmResult; 63 import org.riotfamily.riot.list.support.ListParamsImpl; 64 import org.riotfamily.riot.list.ui.render.RenderContext; 65 import org.riotfamily.riot.security.AccessController; 66 import org.springframework.transaction.PlatformTransactionManager; 67 import org.springframework.transaction.TransactionDefinition; 68 import org.springframework.transaction.TransactionStatus; 69 import org.springframework.transaction.support.DefaultTransactionDefinition; 70 71 75 public class ListSession implements RenderContext { 76 77 private static final DefaultTransactionDefinition TRANSACTION_DEFINITION = 78 new DefaultTransactionDefinition( 79 TransactionDefinition.PROPAGATION_REQUIRED); 80 81 private String key; 82 83 private ListDefinition listDefinition; 84 85 private String parentId; 86 87 private MessageResolver messageResolver; 88 89 private String contextPath; 90 91 private PlatformTransactionManager transactionManager; 92 93 private Form filterForm; 94 95 private TextField searchField; 96 97 private String filterFormHtml; 98 99 private String title; 100 101 private ListConfig listConfig; 102 103 private List listCommands; 104 105 private List itemCommands; 106 107 private String [] defaultCommandIds; 108 109 private ListParamsImpl params; 110 111 private boolean expired; 112 113 public ListSession(String key, ListDefinition listDefinition, 114 String parentId, MessageResolver messageResolver, String contextPath, 115 FormRepository formRepository, 116 FormContextFactory formContextFactory, 117 PlatformTransactionManager transactionManager) { 118 119 this.key = key; 120 this.listDefinition = listDefinition; 121 this.parentId = parentId; 122 this.messageResolver = messageResolver; 123 this.contextPath = contextPath; 124 this.transactionManager = transactionManager; 125 this.listConfig = listDefinition.getListConfig(); 126 127 listCommands = listConfig.getCommands(); 128 itemCommands = listConfig.getColumnCommands(); 129 defaultCommandIds = listConfig.getDefaultCommandIds(); 130 title = listDefinition.createReference(parentId, messageResolver).getLabel(); 131 params = new ListParamsImpl(); 132 133 String formId = listConfig.getFilterFormId(); 134 if (formId != null) { 135 filterForm = formRepository.createForm(formId); 136 } 137 138 if (listConfig.getSearchProperties() != null) { 139 if (filterForm == null) { 140 filterForm = new Form(); 141 filterForm.setBeanClass(HashMap .class); 142 } 143 searchField = new TextField(); 144 searchField.setLabel("Search"); 145 filterForm.addElement(searchField); 146 } 147 148 if (filterForm != null) { 149 filterForm.setFormContext(formContextFactory.createFormContext( 150 messageResolver, contextPath, null)); 151 152 filterForm.setTemplate(ResourceUtils.getPath(getClass(), "FilterForm.ftl")); 153 154 Iterator it = filterForm.getRegisteredElements().iterator(); 155 while (it.hasNext()) { 156 Element e = (Element) it.next(); 157 e.setRequired(false); 158 } 159 160 params.setFilteredProperties(filterForm.getEditorBinder() 161 .getBoundProperties()); 162 163 params.setFilter(filterForm.populateBackingObject()); 164 updateFilterFormHtml(); 165 } 166 167 params.setSearchProperties(listConfig.getSearchProperties()); 168 params.setPageSize(listConfig.getPageSize()); 169 params.setOrder(listConfig.getDefaultOrder()); 170 171 } 172 173 public String getKey() { 174 return key; 175 } 176 177 public void setChooserTarget(EditorDefinition target) { 178 listCommands = Collections.EMPTY_LIST; 179 itemCommands = new ArrayList (); 180 181 ListDefinition targetList = EditorDefinitionUtils 182 .getParentListDefinition(target); 183 184 if (targetList != listDefinition 185 || targetList instanceof TreeDefinition) { 186 187 ListDefinition nextList = targetList; 188 if (listDefinition != targetList) { 189 nextList = EditorDefinitionUtils.getNextListDefinition( 190 listDefinition, targetList); 191 } 192 if (nextList instanceof TreeDefinition) { 193 TreeDefinition tree = (TreeDefinition) nextList; 194 nextList = tree.getNodeListDefinition(); 195 } 196 itemCommands.add(new DescendCommand(nextList, target)); 197 } 198 199 if (listDefinition.getBeanClass().isAssignableFrom( 200 target.getBeanClass())) { 201 202 itemCommands.add(new ChooseCommand(target)); 203 } 204 205 defaultCommandIds = new String [] { DescendCommand.ID, ChooseCommand.ID }; 206 } 207 208 public String getTitle() { 209 return title; 210 } 211 212 private void updateFilterFormHtml() { 213 StringWriter writer = new StringWriter (); 214 filterForm.render(new PrintWriter (writer)); 215 filterFormHtml = writer.toString(); 216 } 217 218 public ListModel getItems(HttpServletRequest request) { 219 Object parent = EditorDefinitionUtils.loadParent( 220 listDefinition, parentId); 221 222 int itemsTotal = listConfig.getDao().getListSize(parent, params); 223 int pageSize = params.getPageSize(); 224 Collection beans = listConfig.getDao().list(parent, params); 225 if (itemsTotal < beans.size()) { 226 itemsTotal = beans.size(); 227 pageSize = itemsTotal; 228 } 229 230 ListModel model = new ListModel(itemsTotal, pageSize, params.getPage()); 231 232 ArrayList items = new ArrayList (beans.size()); 233 int rowIndex = 0; 234 Iterator it = beans.iterator(); 235 while (it.hasNext()) { 236 Object bean = it.next(); 237 ListItem item = new ListItem(); 238 item.setRowIndex(rowIndex++); 239 item.setLastOnPage(!it.hasNext()); 240 item.setObjectId(EditorDefinitionUtils.getObjectId(listDefinition, bean)); 241 item.setColumns(getColumns(bean)); 242 item.setCommands(getCommandStates(itemCommands, 243 item, bean, itemsTotal, request)); 244 245 if (listConfig.getRowStyleProperty() != null) { 246 item.setCssClass(FormatUtils.toCssClass( 247 PropertyUtils.getPropertyAsString(bean, 248 listConfig.getRowStyleProperty()))); 249 } 250 item.setDefaultCommandIds(defaultCommandIds); 251 items.add(item); 252 } 253 model.setItems(items); 254 return model; 255 } 256 257 private List getColumns(Object bean) { 258 ArrayList result = new ArrayList (); 259 Iterator it = listConfig.getColumnConfigs().iterator(); 260 ProtectedBeanWrapper wrapper = new ProtectedBeanWrapper(bean); 261 while (it.hasNext()) { 262 ColumnConfig col = (ColumnConfig) it.next(); 263 String propertyName = col.getProperty(); 264 Object value; 265 if (propertyName != null) { 266 value = wrapper.getPropertyValue(propertyName); 267 } 268 else { 269 value = bean; 270 } 271 StringWriter writer = new StringWriter (); 272 col.getRenderer().render(propertyName, value, this, 273 new PrintWriter (writer)); 274 275 result.add(writer.toString()); 276 } 277 return result; 278 } 279 280 public ListModel getModel(HttpServletRequest request) { 281 ListModel model = getItems(request); 282 283 model.setEditorId(listDefinition.getId()); 284 model.setParentId(parentId); 285 model.setItemCommandCount(itemCommands.size()); 286 model.setListCommands(getListCommands(request)); 287 model.setCssClass(listConfig.getId()); 288 289 boolean sortableDao = listConfig.getDao() instanceof SortableDao; 290 291 ArrayList columns = new ArrayList (); 292 Iterator it = listConfig.getColumnConfigs().iterator(); 293 while (it.hasNext()) { 294 ColumnConfig config = (ColumnConfig) it.next(); 295 ListColumn column = new ListColumn(); 296 column.setProperty(config.getProperty()); 297 column.setHeading(getHeading(config.getProperty(), 298 config.getLookupLevel())); 299 300 column.setSortable(sortableDao && config.isSortable()); 301 column.setCssClass(FormatUtils.toCssClass(config.getProperty())); 302 if (params.hasOrder() && params.getPrimaryOrder() 303 .getProperty().equals(config.getProperty())) { 304 305 column.setSorted(true); 306 column.setAscending(params.getPrimaryOrder().isAscending()); 307 } 308 columns.add(column); 309 } 310 model.setColumns(columns); 311 model.setFilterFormHtml(filterFormHtml); 312 return model; 313 } 314 315 private String getHeading(String property, int lookupLevel) { 316 return getHeading(getBeanClass(), property, lookupLevel); 317 } 318 319 private String getHeading(Class clazz, String property, int lookupLevel) { 320 if (property == null) { 321 return null; 322 } 323 if (clazz != null) { 324 String root = property; 325 int pos = property.indexOf('.'); 326 if (pos > 0) { 327 root = property.substring(0, pos); 328 } 329 if (lookupLevel > 1) { 330 clazz = PropertyUtils.getPropertyType(clazz, root); 331 if (pos > 0) { 332 String nestedProperty = property.substring(pos + 1); 333 return getHeading(clazz, nestedProperty, lookupLevel - 1); 334 } 335 else { 336 return messageResolver.getClassLabel(null, clazz); 337 } 338 } 339 } 340 return messageResolver.getPropertyLabel( 341 getListId(), clazz, property); 342 } 343 344 public ListModel sort(String property, HttpServletRequest request) { 345 ColumnConfig col = listConfig.getColumnConfig(property); 346 params.orderBy(property, col.isAscending(), col.isCaseSensitive()); 347 return getModel(request); 348 } 349 350 public String [] getSearchProperties() { 351 return listConfig.getSearchProperties(); 352 } 353 354 public String getSearchQuery() { 355 return params.getSearch(); 356 } 357 358 public String getFilterFormHtml() { 359 return filterFormHtml; 360 } 361 362 public ListModel filter(Map filter, HttpServletRequest request) { 363 if (filterForm != null) { 364 filterForm.processRequest(new SimpleFormRequest(filter)); 365 params.setFilter(filterForm.populateBackingObject()); 366 if (searchField != null) { 367 params.setSearch(searchField.getText()); 368 } 369 updateFilterFormHtml(); 370 } 371 params.setPage(1); 372 ListModel result = getItems(request); 373 result.setFilterFormHtml(filterFormHtml); 374 return result; 375 } 376 377 public ListModel gotoPage(int page, HttpServletRequest request) { 378 params.setPage(page); 379 return getItems(request); 380 } 381 382 public boolean hasListCommands() { 383 return !listCommands.isEmpty(); 384 } 385 386 public List getListCommands(HttpServletRequest request) { 387 return getCommandStates(listCommands, null, null, -1, request); 389 } 390 391 public List getFormCommands(String objectId, HttpServletRequest request) { 392 Object bean = null; 393 if (objectId != null) { 394 bean = listConfig.getDao().load(objectId); 395 } 396 return getCommandStates(listConfig.getFormCommands(), 397 new ListItem(objectId), bean, 1, request); 398 } 399 400 private List getCommandStates(List commands, ListItem item, Object bean, 401 int itemsTotal, HttpServletRequest request) { 402 403 ArrayList result = new ArrayList (); 404 CommandContextImpl context = new CommandContextImpl(this, request); 405 context.setBean(bean); 406 context.setItem(item); 407 context.setItemsTotal(itemsTotal); 408 Iterator it = commands.iterator(); 409 while (it.hasNext()) { 410 Command command = (Command) it.next(); 411 CommandState state = command.getState(context); 412 boolean granted = AccessController.isGranted( 413 state.getAction(), bean); 414 415 state.setEnabled(state.isEnabled() && granted); 416 result.add(state); 417 } 418 return result; 419 } 420 421 public CommandResult execCommand(ListItem item, String commandId, 422 boolean confirmed, HttpServletRequest request, 423 HttpServletResponse response) { 424 425 Collection commands = item != null ? itemCommands : listCommands; 426 Command command = getCommand(commands, commandId); 427 Object bean = null; 428 CommandContextImpl context = new CommandContextImpl(this, request); 429 if (item != null) { 430 context.setItem(item); 431 } 432 else { 433 bean = EditorDefinitionUtils.loadParent(listDefinition, parentId); 434 context.setBean(bean); 435 } 436 String action = command.getState(context).getAction(); 437 if (AccessController.isGranted(action, bean)) { 438 if (!confirmed) { 439 String message = command.getConfirmationMessage(context); 440 if (message != null) { 441 return new ConfirmResult(item, commandId, message); 442 } 443 } 444 TransactionStatus status = transactionManager.getTransaction(TRANSACTION_DEFINITION); 445 CommandResult result; 446 try { 447 result = command.execute(context); 448 } 449 catch (RuntimeException e) { 450 transactionManager.rollback(status); 451 throw e; 452 } 453 transactionManager.commit(status); 454 return result; 455 } 456 else { 457 return null; 458 } 459 } 460 461 private Command getCommand(Collection commands, String id) { 462 Iterator it = commands.iterator(); 463 while (it.hasNext()) { 464 Command command = (Command) it.next(); 465 if (id.equals(command.getId())) { 466 return command; 467 } 468 } 469 throw new IllegalArgumentException ("No such command: " + id); 470 } 471 472 public Object loadBean(String objectId) { 473 return listDefinition.getListConfig().getDao().load(objectId); 474 } 475 476 public ListDefinition getListDefinition() { 477 return listDefinition; 478 } 479 480 public String getListId() { 481 return listDefinition.getListId(); 482 } 483 484 public ListParamsImpl getParams() { 485 return params; 486 } 487 488 public String getParentId() { 489 return parentId; 490 } 491 492 public Class getBeanClass() { 493 return listDefinition.getBeanClass(); 494 } 495 496 public MessageResolver getMessageResolver() { 497 return messageResolver; 498 } 499 500 public String getContextPath() { 501 return contextPath; 502 } 503 504 void invalidate() { 505 expired = true; 506 } 507 508 public boolean isExpired() { 509 return expired; 510 } 511 512 } 513 | Popular Tags |