Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||||||
TableView |
|
| 2.3658536585365852;2.366 |
1 | // Copyright 2004, 2005 The Apache Software Foundation |
|
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 org.apache.tapestry.contrib.table.components; |
|
16 | ||
17 | import org.apache.hivemind.ApplicationRuntimeException; |
|
18 | import org.apache.tapestry.BaseComponent; |
|
19 | import org.apache.tapestry.IComponent; |
|
20 | import org.apache.tapestry.IMarkupWriter; |
|
21 | import org.apache.tapestry.IRequestCycle; |
|
22 | import org.apache.tapestry.contrib.table.model.*; |
|
23 | import org.apache.tapestry.contrib.table.model.common.BasicTableModelWrap; |
|
24 | import org.apache.tapestry.contrib.table.model.simple.SimpleListTableDataModel; |
|
25 | import org.apache.tapestry.contrib.table.model.simple.SimpleTableColumnModel; |
|
26 | import org.apache.tapestry.contrib.table.model.simple.SimpleTableModel; |
|
27 | import org.apache.tapestry.contrib.table.model.simple.SimpleTableState; |
|
28 | import org.apache.tapestry.event.PageBeginRenderListener; |
|
29 | import org.apache.tapestry.event.PageDetachListener; |
|
30 | import org.apache.tapestry.event.PageEvent; |
|
31 | ||
32 | import java.io.Serializable; |
|
33 | import java.util.ArrayList; |
|
34 | import java.util.Collection; |
|
35 | import java.util.Iterator; |
|
36 | import java.util.List; |
|
37 | ||
38 | /** |
|
39 | * A low level Table component that wraps all other low level Table components. |
|
40 | * This component carries the |
|
41 | * {@link org.apache.tapestry.contrib.table.model.ITableModel}that is used by |
|
42 | * the other Table components. Please see the documentation of |
|
43 | * {@link org.apache.tapestry.contrib.table.model.ITableModel}if you need to |
|
44 | * know more about how a table is represented. |
|
45 | * <p> |
|
46 | * This component also handles the saving of the state of the model using an |
|
47 | * {@link org.apache.tapestry.contrib.table.model.ITableSessionStateManager}to |
|
48 | * determine what part of the model is to be saved and an |
|
49 | * {@link org.apache.tapestry.contrib.table.model.ITableSessionStoreManager}to |
|
50 | * determine how to save it. |
|
51 | * <p> |
|
52 | * Upon the beginning of a new request cycle when the table model is first |
|
53 | * needed, the model is obtained using the following process: |
|
54 | * <ul> |
|
55 | * <li>The persistent state of the table is loaded. If the |
|
56 | * tableSessionStoreManager binding has not been bound, the state is loaded from |
|
57 | * a persistent property within the component (it is null at the beginning). |
|
58 | * Otherwise the supplied |
|
59 | * {@link org.apache.tapestry.contrib.table.model.ITableSessionStoreManager}is |
|
60 | * used to load the persistent state. |
|
61 | * <li>The table model is recreated using the |
|
62 | * {@link org.apache.tapestry.contrib.table.model.ITableSessionStateManager}that |
|
63 | * could be supplied using the tableSessionStateManager binding (but has a |
|
64 | * default value and is therefore not required). |
|
65 | * <li>If the |
|
66 | * {@link org.apache.tapestry.contrib.table.model.ITableSessionStateManager}returns |
|
67 | * null, then a table model is taken from the tableModel binding. Thus, if the |
|
68 | * {@link org.apache.tapestry.contrib.table.model.common.NullTableSessionStateManager}is |
|
69 | * used, the table model would be taken from the tableModel binding every time. |
|
70 | * </ul> |
|
71 | * Just before the rendering phase the persistent state of the model is saved in |
|
72 | * the session. This process occurs in reverse: |
|
73 | * <ul> |
|
74 | * <li>The persistent state of the model is taken via the |
|
75 | * {@link org.apache.tapestry.contrib.table.model.ITableSessionStateManager}. |
|
76 | * <li>If the tableSessionStoreManager binding has not been bound, the |
|
77 | * persistent state is saved as a persistent page property. Otherwise the |
|
78 | * supplied |
|
79 | * {@link org.apache.tapestry.contrib.table.model.ITableSessionStoreManager}is |
|
80 | * used to save the persistent state. Use of the |
|
81 | * {@link org.apache.tapestry.contrib.table.model.ITableSessionStoreManager}is |
|
82 | * usually necessary when tables with the same model have to be used across |
|
83 | * multiple pages, and hence the state has to be saved in the Visit, rather than |
|
84 | * in a persistent component property. |
|
85 | * </ul> |
|
86 | * <p> |
|
87 | * <p> |
|
88 | * Please see the Component Reference for details on how to use this component. [ |
|
89 | * <a |
|
90 | * href="../../../../../../../ComponentReference/contrib.TableView.html">Component |
|
91 | * Reference </a>] |
|
92 | * |
|
93 | * @author mindbridge |
|
94 | */ |
|
95 | public abstract class TableView extends BaseComponent implements |
|
96 | PageDetachListener, PageBeginRenderListener, ITableModelSource |
|
97 | { |
|
98 | ||
99 | // Component properties |
|
100 | 0 | private ITableSessionStateManager m_objDefaultSessionStateManager = null; |
101 | ||
102 | 0 | private ITableColumnModel m_objColumnModel = null; |
103 | ||
104 | // Transient objects |
|
105 | private ITableModel m_objTableModel; |
|
106 | ||
107 | private ITableModel m_objCachedTableModelValue; |
|
108 | ||
109 | /** |
|
110 | * The component constructor. Invokes the component member initializations. |
|
111 | */ |
|
112 | public TableView() |
|
113 | 0 | { |
114 | 0 | initialize(); |
115 | 0 | } |
116 | ||
117 | /** @since 4.0 */ |
|
118 | public abstract TableColumnModelSource getModelSource(); |
|
119 | ||
120 | /** @since 4.0 */ |
|
121 | public abstract IAdvancedTableColumnSource getColumnSource(); |
|
122 | ||
123 | // enhanced parameter methods |
|
124 | public abstract ITableModel getTableModelValue(); |
|
125 | ||
126 | public abstract Object getSource(); |
|
127 | ||
128 | public abstract Object getColumns(); |
|
129 | ||
130 | public abstract int getInitialPage(); |
|
131 | ||
132 | public abstract String getInitialSortColumn(); |
|
133 | ||
134 | public abstract boolean getInitialSortOrder(); |
|
135 | ||
136 | public abstract ITableSessionStateManager getTableSessionStateManager(); |
|
137 | ||
138 | public abstract ITableSessionStoreManager getTableSessionStoreManager(); |
|
139 | ||
140 | public abstract IComponent getColumnSettingsContainer(); |
|
141 | ||
142 | public abstract int getPageSize(); |
|
143 | ||
144 | public abstract String getPersist(); |
|
145 | ||
146 | // enhanced property methods |
|
147 | public abstract Serializable getSessionState(); |
|
148 | ||
149 | public abstract void setSessionState(Serializable sessionState); |
|
150 | ||
151 | public abstract Serializable getClientState(); |
|
152 | ||
153 | public abstract void setClientState(Serializable sessionState); |
|
154 | ||
155 | public abstract Serializable getClientAppState(); |
|
156 | ||
157 | public abstract void setClientAppState(Serializable sessionState); |
|
158 | ||
159 | public abstract List getTableActions(); |
|
160 | ||
161 | public abstract void setTableActions(List actions); |
|
162 | ||
163 | /** |
|
164 | * Invokes the component member initializations. |
|
165 | * |
|
166 | * @see org.apache.tapestry.event.PageDetachListener#pageDetached(PageEvent) |
|
167 | */ |
|
168 | public void pageDetached(PageEvent objEvent) |
|
169 | { |
|
170 | 0 | initialize(); |
171 | 0 | } |
172 | ||
173 | /** |
|
174 | * Initialize the component member variables. |
|
175 | */ |
|
176 | private void initialize() |
|
177 | { |
|
178 | 0 | m_objTableModel = null; |
179 | 0 | m_objCachedTableModelValue = null; |
180 | 0 | } |
181 | ||
182 | /** |
|
183 | * Resets the table by removing any stored table state. This means that the |
|
184 | * current column to sort on and the current page will be forgotten and all |
|
185 | * data will be reloaded. |
|
186 | */ |
|
187 | public void reset() |
|
188 | { |
|
189 | 0 | initialize(); |
190 | 0 | storeSessionState(null); |
191 | 0 | } |
192 | ||
193 | public ITableModel getCachedTableModelValue() |
|
194 | { |
|
195 | 0 | if (m_objCachedTableModelValue == null) |
196 | 0 | m_objCachedTableModelValue = getTableModelValue(); |
197 | 0 | return m_objCachedTableModelValue; |
198 | } |
|
199 | ||
200 | /** |
|
201 | * Returns the tableModel. |
|
202 | * |
|
203 | * @return ITableModel the table model used by the table components |
|
204 | */ |
|
205 | public ITableModel getTableModel() |
|
206 | { |
|
207 | // if null, first try to recreate the model from the session state |
|
208 | 0 | if (m_objTableModel == null) |
209 | { |
|
210 | 0 | Serializable objState = loadSessionState(); |
211 | 0 | ITableSessionStateManager objStateManager = getTableSessionStateManager(); |
212 | 0 | m_objTableModel = objStateManager.recreateTableModel(objState); |
213 | } |
|
214 | ||
215 | // if the session state does not help, get the model from the binding |
|
216 | 0 | if (m_objTableModel == null) |
217 | 0 | m_objTableModel = getCachedTableModelValue(); |
218 | ||
219 | // if the model from the binding is null, build a model from source and |
|
220 | // columns |
|
221 | 0 | if (m_objTableModel == null) |
222 | 0 | m_objTableModel = generateTableModel(null); |
223 | ||
224 | 0 | if (m_objTableModel == null) |
225 | 0 | throw new ApplicationRuntimeException(TableMessages.missingTableModel(this)); |
226 | ||
227 | 0 | return m_objTableModel; |
228 | } |
|
229 | ||
230 | /** |
|
231 | * Generate a table model using the 'source' and 'columns' parameters. |
|
232 | * |
|
233 | * @return the newly generated table model |
|
234 | */ |
|
235 | protected ITableModel generateTableModel(SimpleTableState objState) |
|
236 | { |
|
237 | 0 | SimpleTableState usableObjState = objState; |
238 | // create a new table state if none is passed |
|
239 | 0 | if (usableObjState == null) |
240 | { |
|
241 | 0 | usableObjState = new SimpleTableState(); |
242 | 0 | usableObjState.getSortingState().setSortColumn(getInitialSortColumn(), |
243 | getInitialSortOrder()); |
|
244 | 0 | usableObjState.getPagingState().setCurrentPage(getInitialPage()); |
245 | } |
|
246 | ||
247 | // update the page size if set in the parameter |
|
248 | 0 | if (isParameterBound("pageSize")) |
249 | 0 | usableObjState.getPagingState().setPageSize(getPageSize()); |
250 | ||
251 | // get the column model. if not possible, return null. |
|
252 | 0 | ITableColumnModel objColumnModel = getTableColumnModel(); |
253 | 0 | if (objColumnModel == null) return null; |
254 | ||
255 | 0 | Object objSourceValue = getSource(); |
256 | 0 | if (objSourceValue == null) return null; |
257 | ||
258 | // if the source parameter is of type {@link IBasicTableModel}, |
|
259 | // create and return an appropriate wrapper |
|
260 | 0 | if (objSourceValue instanceof IBasicTableModel) |
261 | 0 | return new BasicTableModelWrap((IBasicTableModel) objSourceValue, |
262 | objColumnModel, usableObjState); |
|
263 | ||
264 | // otherwise, the source parameter must contain the data to be displayed |
|
265 | 0 | ITableDataModel objDataModel = null; |
266 | 0 | if (objSourceValue instanceof Object[]) |
267 | 0 | objDataModel = new SimpleListTableDataModel( |
268 | (Object[]) objSourceValue); |
|
269 | 0 | else if (objSourceValue instanceof List) |
270 | 0 | objDataModel = new SimpleListTableDataModel((List) objSourceValue); |
271 | 0 | else if (objSourceValue instanceof Collection) |
272 | 0 | objDataModel = new SimpleListTableDataModel( |
273 | (Collection) objSourceValue); |
|
274 | 0 | else if (objSourceValue instanceof Iterator) |
275 | 0 | objDataModel = new SimpleListTableDataModel( |
276 | (Iterator) objSourceValue); |
|
277 | ||
278 | 0 | if (objDataModel == null) |
279 | 0 | throw new ApplicationRuntimeException(TableMessages |
280 | .invalidTableSource(this, objSourceValue)); |
|
281 | ||
282 | 0 | return new SimpleTableModel(objDataModel, objColumnModel, usableObjState); |
283 | } |
|
284 | ||
285 | /** |
|
286 | * Returns the table column model as specified by the 'columns' binding. If |
|
287 | * the value of the 'columns' binding is of a type different than |
|
288 | * ITableColumnModel, this method makes the appropriate conversion. |
|
289 | * |
|
290 | * @return The table column model as specified by the 'columns' binding |
|
291 | */ |
|
292 | protected ITableColumnModel getTableColumnModel() |
|
293 | { |
|
294 | 0 | Object objColumns = getColumns(); |
295 | ||
296 | 0 | if (objColumns == null) return null; |
297 | ||
298 | 0 | if (objColumns instanceof ITableColumnModel) { return (ITableColumnModel) objColumns; } |
299 | ||
300 | 0 | if (objColumns instanceof Iterator) |
301 | { |
|
302 | // convert to List |
|
303 | 0 | Iterator objColumnsIterator = (Iterator) objColumns; |
304 | 0 | List arrColumnsList = new ArrayList(); |
305 | 0 | addAll(arrColumnsList, objColumnsIterator); |
306 | 0 | objColumns = arrColumnsList; |
307 | } |
|
308 | ||
309 | 0 | if (objColumns instanceof List) |
310 | { |
|
311 | // validate that the list contains only ITableColumn instances |
|
312 | 0 | List arrColumnsList = (List) objColumns; |
313 | 0 | int nColumnsNumber = arrColumnsList.size(); |
314 | 0 | for(int i = 0; i < nColumnsNumber; i++) |
315 | { |
|
316 | 0 | if (!(arrColumnsList.get(i) instanceof ITableColumn)) |
317 | 0 | throw new ApplicationRuntimeException(TableMessages |
318 | .columnsOnlyPlease(this)); |
|
319 | } |
|
320 | // objColumns = arrColumnsList.toArray(new |
|
321 | // ITableColumn[nColumnsNumber]); |
|
322 | 0 | return new SimpleTableColumnModel(arrColumnsList); |
323 | } |
|
324 | ||
325 | 0 | if (objColumns instanceof ITableColumn[]) { return new SimpleTableColumnModel( |
326 | (ITableColumn[]) objColumns); } |
|
327 | ||
328 | 0 | if (objColumns instanceof String) |
329 | { |
|
330 | 0 | String strColumns = (String) objColumns; |
331 | 0 | if (getBinding("columns").isInvariant()) |
332 | { |
|
333 | // if the binding is invariant, create the columns only once |
|
334 | 0 | if (m_objColumnModel == null) |
335 | 0 | m_objColumnModel = generateTableColumnModel(strColumns); |
336 | 0 | return m_objColumnModel; |
337 | } |
|
338 | ||
339 | // if the binding is not invariant, create them every time |
|
340 | 0 | return generateTableColumnModel(strColumns); |
341 | } |
|
342 | ||
343 | 0 | throw new ApplicationRuntimeException(TableMessages |
344 | .invalidTableColumns(this, objColumns)); |
|
345 | } |
|
346 | ||
347 | private void addAll(List arrColumnsList, Iterator objColumnsIterator) |
|
348 | { |
|
349 | 0 | while(objColumnsIterator.hasNext()) |
350 | 0 | arrColumnsList.add(objColumnsIterator.next()); |
351 | 0 | } |
352 | ||
353 | /** |
|
354 | * Generate a table column model out of the description string provided. |
|
355 | * Entries in the description string are separated by commas. Each column |
|
356 | * entry is of the format name, name:expression, or |
|
357 | * name:displayName:expression. An entry prefixed with ! represents a |
|
358 | * non-sortable column. If the whole description string is prefixed with *, |
|
359 | * it represents columns to be included in a Form. |
|
360 | * |
|
361 | * @param strDesc |
|
362 | * the description of the column model to be generated |
|
363 | * @return a table column model based on the provided description |
|
364 | */ |
|
365 | protected ITableColumnModel generateTableColumnModel(String strDesc) |
|
366 | { |
|
367 | 0 | IComponent objColumnSettingsContainer = getColumnSettingsContainer(); |
368 | 0 | IAdvancedTableColumnSource objColumnSource = getColumnSource(); |
369 | ||
370 | 0 | return getModelSource().generateTableColumnModel(objColumnSource, |
371 | strDesc, this, objColumnSettingsContainer); |
|
372 | } |
|
373 | ||
374 | /** |
|
375 | * The default session state manager to be used in case no such manager is |
|
376 | * provided by the corresponding parameter. |
|
377 | * |
|
378 | * @return the default session state manager |
|
379 | */ |
|
380 | public ITableSessionStateManager getDefaultTableSessionStateManager() |
|
381 | { |
|
382 | 0 | if (m_objDefaultSessionStateManager == null) |
383 | 0 | m_objDefaultSessionStateManager = new TableViewSessionStateManager( |
384 | this); |
|
385 | 0 | return m_objDefaultSessionStateManager; |
386 | } |
|
387 | ||
388 | /** |
|
389 | * Invoked when there is a modification of the table state and it needs to |
|
390 | * be saved. |
|
391 | * |
|
392 | * @see org.apache.tapestry.contrib.table.model.ITableModelSource#fireObservedStateChange() |
|
393 | */ |
|
394 | public void fireObservedStateChange() |
|
395 | { |
|
396 | 0 | saveSessionState(); |
397 | 0 | } |
398 | ||
399 | /** |
|
400 | * Ensures that the table state is saved before the render phase begins in |
|
401 | * case there are modifications for which {@link #fireObservedStateChange()}has |
|
402 | * not been invoked. |
|
403 | * |
|
404 | * @see org.apache.tapestry.event.PageBeginRenderListener#pageBeginRender(org.apache.tapestry.event.PageEvent) |
|
405 | */ |
|
406 | public void pageBeginRender(PageEvent event) |
|
407 | { |
|
408 | 0 | executeTableActions(); |
409 | ||
410 | // 'suspenders': save the table model if it has been already loaded. |
|
411 | // this means that if a change has been made explicitly in a listener, |
|
412 | // it will be saved. this is the last place before committing the |
|
413 | // changes |
|
414 | // where a save can occur |
|
415 | 0 | if (m_objTableModel != null) saveSessionState(); |
416 | 0 | } |
417 | ||
418 | /** |
|
419 | * Saves the table state using the SessionStateManager to determine what to |
|
420 | * save and the SessionStoreManager to determine where to save it. |
|
421 | */ |
|
422 | protected void saveSessionState() |
|
423 | { |
|
424 | 0 | ITableModel objModel = getTableModel(); |
425 | 0 | Serializable objState = getTableSessionStateManager().getSessionState( |
426 | objModel); |
|
427 | 0 | storeSessionState(objState); |
428 | 0 | } |
429 | ||
430 | /** |
|
431 | * Loads the table state using the SessionStoreManager. |
|
432 | * |
|
433 | * @return the stored table state |
|
434 | */ |
|
435 | protected Serializable loadSessionState() |
|
436 | { |
|
437 | 0 | ITableSessionStoreManager objManager = getTableSessionStoreManager(); |
438 | 0 | if (objManager != null) |
439 | 0 | return objManager.loadState(getPage().getRequestCycle()); |
440 | 0 | String strPersist = getPersist(); |
441 | 0 | if (strPersist.equals("client") || strPersist.equals("client:page")) |
442 | 0 | return getClientState(); |
443 | 0 | else if (strPersist.equals("client:app")) |
444 | 0 | return getClientAppState(); |
445 | 0 | else return getSessionState(); |
446 | } |
|
447 | ||
448 | /** |
|
449 | * Stores the table state using the SessionStoreManager. |
|
450 | * |
|
451 | * @param objState |
|
452 | * the table state to store |
|
453 | */ |
|
454 | protected void storeSessionState(Serializable objState) |
|
455 | { |
|
456 | 0 | ITableSessionStoreManager objManager = getTableSessionStoreManager(); |
457 | 0 | if (objManager != null) |
458 | 0 | objManager.saveState(getPage().getRequestCycle(), objState); |
459 | else |
|
460 | { |
|
461 | 0 | String strPersist = getPersist(); |
462 | 0 | if (strPersist.equals("client") || strPersist.equals("client:page")) |
463 | 0 | setClientState(objState); |
464 | 0 | else if (strPersist.equals("client:app")) |
465 | 0 | setClientAppState(objState); |
466 | 0 | else setSessionState(objState); |
467 | } |
|
468 | 0 | } |
469 | ||
470 | /** |
|
471 | * Make sure that the values stored in the model are useable and correct. |
|
472 | * The changes made here are not saved. |
|
473 | */ |
|
474 | protected void validateValues() |
|
475 | { |
|
476 | 0 | ITableModel objModel = getTableModel(); |
477 | ||
478 | // make sure current page is within the allowed range |
|
479 | 0 | ITablePagingState objPagingState = objModel.getPagingState(); |
480 | 0 | int nCurrentPage = objPagingState.getCurrentPage(); |
481 | 0 | int nPageCount = objModel.getPageCount(); |
482 | 0 | if (nCurrentPage >= nPageCount) |
483 | { |
|
484 | // the current page is greater than the page count. adjust. |
|
485 | 0 | nCurrentPage = nPageCount - 1; |
486 | 0 | objPagingState.setCurrentPage(nCurrentPage); |
487 | } |
|
488 | 0 | if (nCurrentPage < 0) |
489 | { |
|
490 | // the current page is before the first page. adjust. |
|
491 | 0 | nCurrentPage = 0; |
492 | 0 | objPagingState.setCurrentPage(nCurrentPage); |
493 | } |
|
494 | 0 | } |
495 | ||
496 | /** |
|
497 | * Stores a pointer to this component in the Request Cycle while rendering |
|
498 | * so that wrapped components have access to it. |
|
499 | * |
|
500 | * @see org.apache.tapestry.BaseComponent#renderComponent(IMarkupWriter, |
|
501 | * IRequestCycle) |
|
502 | */ |
|
503 | protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle) |
|
504 | { |
|
505 | 0 | Object objOldValue = cycle.getAttribute(ITableModelSource.TABLE_MODEL_SOURCE_ATTRIBUTE); |
506 | 0 | cycle.setAttribute(ITableModelSource.TABLE_MODEL_SOURCE_ATTRIBUTE, this); |
507 | ||
508 | 0 | initialize(); |
509 | 0 | validateValues(); |
510 | ||
511 | 0 | super.renderComponent(writer, cycle); |
512 | ||
513 | 0 | cycle.setAttribute(ITableModelSource.TABLE_MODEL_SOURCE_ATTRIBUTE, |
514 | objOldValue); |
|
515 | 0 | } |
516 | ||
517 | /** |
|
518 | * Stores the provided table action. |
|
519 | */ |
|
520 | public void storeTableAction(ITableAction action) |
|
521 | { |
|
522 | 0 | List actions = getTableActions(); |
523 | 0 | if (actions == null) |
524 | { |
|
525 | 0 | actions = new ArrayList(5); |
526 | 0 | setTableActions(actions); |
527 | } |
|
528 | ||
529 | 0 | actions.add(action); |
530 | 0 | } |
531 | ||
532 | /** |
|
533 | * Executes the stored table actions. |
|
534 | */ |
|
535 | public void executeTableActions() |
|
536 | { |
|
537 | 0 | List actions = getTableActions(); |
538 | 0 | if (actions == null || actions.isEmpty()) return; |
539 | ||
540 | // save the actions and clear the list |
|
541 | 0 | List savedActions = new ArrayList(actions); |
542 | 0 | actions.clear(); |
543 | ||
544 | 0 | ITableModel objTableModel = getTableModel(); |
545 | 0 | for(Iterator it = savedActions.iterator(); it.hasNext();) |
546 | { |
|
547 | 0 | ITableAction action = (ITableAction) it.next(); |
548 | 0 | action.executeTableAction(objTableModel); |
549 | 0 | } |
550 | ||
551 | // ensure that the changes are saved |
|
552 | 0 | fireObservedStateChange(); |
553 | 0 | } |
554 | ||
555 | } |