001: /***************************************************************
002: * This file is part of the [fleXive](R) project.
003: *
004: * Copyright (c) 1999-2007
005: * UCS - unique computing solutions gmbh (http://www.ucs.at)
006: * All rights reserved
007: *
008: * The [fleXive](R) project is free software; you can redistribute
009: * it and/or modify it under the terms of the GNU General Public
010: * License as published by the Free Software Foundation;
011: * either version 2 of the License, or (at your option) any
012: * later version.
013: *
014: * The GNU General Public License can be found at
015: * http://www.gnu.org/copyleft/gpl.html.
016: * A copy is found in the textfile GPL.txt and important notices to the
017: * license from the author are found in LICENSE.txt distributed with
018: * these libraries.
019: *
020: * This library is distributed in the hope that it will be useful,
021: * but WITHOUT ANY WARRANTY; without even the implied warranty of
022: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
023: * GNU General Public License for more details.
024: *
025: * For further information about UCS - unique computing solutions gmbh,
026: * please see the company website: http://www.ucs.at
027: *
028: * For further information about [fleXive](R), please see the
029: * project website: http://www.flexive.org
030: *
031: *
032: * This copyright notice MUST APPEAR in all copies of the file!
033: ***************************************************************/package com.flexive.war.beans.admin.search;
034:
035: import com.flexive.faces.FxJsfUtils;
036: import com.flexive.faces.beans.MessageBean;
037: import com.flexive.faces.beans.SearchResultBean;
038: import com.flexive.faces.beans.SelectBean;
039: import com.flexive.faces.listener.JsfPhaseListener;
040: import com.flexive.faces.messages.FxFacesMsgErr;
041: import com.flexive.faces.messages.FxFacesMsgInfo;
042: import com.flexive.faces.messages.FxFacesMsgWarn;
043: import com.flexive.shared.CacheAdmin;
044: import com.flexive.shared.EJBLookup;
045: import com.flexive.shared.FxSharedUtils;
046: import com.flexive.shared.exceptions.FxApplicationException;
047: import com.flexive.shared.exceptions.FxNotFoundException;
048: import com.flexive.shared.exceptions.FxRuntimeException;
049: import com.flexive.shared.search.*;
050: import com.flexive.shared.structure.FxEnvironment;
051: import com.flexive.shared.structure.FxPropertyAssignment;
052: import com.flexive.shared.structure.FxType;
053: import org.apache.myfaces.component.html.ext.HtmlDataTable;
054:
055: import javax.faces.component.UIComponent;
056: import javax.faces.component.UIViewRoot;
057: import javax.faces.context.FacesContext;
058: import javax.faces.event.ActionEvent;
059: import javax.faces.event.PhaseId;
060: import javax.faces.model.DataModel;
061: import javax.faces.model.SelectItem;
062: import javax.faces.model.SelectItemGroup;
063: import java.util.*;
064:
065: /**
066: * Bean for creating and updating result preferences.
067: *
068: * @author Daniel Lichtenberger (daniel.lichtenberger@flexive.com), UCS - unique computing solutions gmbh (http://www.ucs.at)
069: * @version $Rev: 1 $
070: */
071: public class ResultPreferencesBean {
072: /**
073: * Tomahawk HtmlDataTable wrapper that exposes the internal data model.
074: * We need this for other components depending on data tables that persist their
075: * model in their viewState (aka preserveDataModel=true).
076: */
077: public static class WrappedHtmlDataTable extends HtmlDataTable {
078: @SuppressWarnings({"MethodOverridesPrivateMethodOfSuperclass"})
079: @Override
080: public DataModel getDataModel() {
081: return super .getDataModel();
082: }
083: }
084:
085: private long type = -1;
086: private ResultViewType viewType = ResultViewType.LIST;
087: private ResultLocation location = AdminResultLocations.ADMIN;
088: private ResultPreferencesEdit resultPreferences = null;
089: private String addPropertyName = null;
090: private String addOrderByName = null;
091: private SortDirection addOrderByDirection = SortDirection.ASCENDING;
092: private int editColumnIndex = -1;
093:
094: // cached select list
095: private List<SelectItem> properties = null;
096: private long cachedTypeId = -1;
097: private Map<String, String> propertyLabelMap = null;
098: private List<SelectItem> types;
099:
100: // form components
101: private WrappedHtmlDataTable selectedColumnsTable = null;
102:
103: public String show() {
104: return "resultPreferences";
105: }
106:
107: public String save() {
108: try {
109: EJBLookup.getResultPreferencesEngine().save(
110: getResultPreferences(), type, viewType, location);
111: new FxFacesMsgInfo("ResultPreferences.nfo.saved")
112: .addToContext();
113: } catch (FxApplicationException e) {
114: new FxFacesMsgErr("ResultPreferences.err.save", e)
115: .addToContext();
116: }
117: return show();
118: }
119:
120: public String cancel() {
121: return ((SearchResultBean) FxJsfUtils
122: .getManagedBean("fxSearchResultBean")).show();
123: }
124:
125: public void addColumnProperty(ActionEvent event) {
126: getResultPreferences().addSelectedColumn(
127: new ResultColumnInfo(Table.CONTENT, addPropertyName,
128: null));
129: addPropertyName = null;
130: }
131:
132: public void removeColumnProperty(ActionEvent event) {
133: if (editColumnIndex == -1) {
134: return;
135: }
136: try {
137: final ResultColumnInfo info = getResultPreferences()
138: .removeSelectedColumn(editColumnIndex);
139: // remove property from order by clause too
140: List<ResultOrderByInfo> removeOrderByColumns = new ArrayList<ResultOrderByInfo>();
141: for (ResultOrderByInfo orderByInfo : getResultPreferences()
142: .getOrderByColumns()) {
143: if (orderByInfo.getColumnName().equals(
144: info.getColumnName())) {
145: removeOrderByColumns.add(orderByInfo);
146: }
147: }
148: for (ResultOrderByInfo removeInfo : removeOrderByColumns) {
149: getResultPreferences().removeOrderByColumn(removeInfo);
150: }
151: } catch (FxRuntimeException e) {
152: new FxFacesMsgErr("ResultPreferences.err.removeRow", e)
153: .addToContext();
154: }
155: }
156:
157: public void moveColumnPropertyUp(ActionEvent event) {
158: moveColumnProperty(-1);
159: }
160:
161: public void moveColumnPropertyDown(ActionEvent event) {
162: moveColumnProperty(1);
163: }
164:
165: private void moveColumnProperty(int moveDelta) {
166: if (editColumnIndex == -1) {
167: return;
168: }
169: try {
170: ResultColumnInfo info = getResultPreferences()
171: .removeSelectedColumn(editColumnIndex);
172: getResultPreferences().addSelectedColumn(
173: editColumnIndex + moveDelta, info);
174: } catch (FxRuntimeException e) {
175: new FxFacesMsgErr("ResultPreferences.err.moveRow", e)
176: .addToContext();
177: }
178: }
179:
180: public void moveOrderByPropertyUp(ActionEvent event) {
181: moveOrderByProperty(-1);
182: }
183:
184: public void moveOrderByPropertyDown(ActionEvent event) {
185: moveOrderByProperty(1);
186: }
187:
188: private void moveOrderByProperty(int moveDelta) {
189: if (editColumnIndex == -1) {
190: return;
191: }
192: try {
193: ResultOrderByInfo info = getResultPreferences()
194: .removeOrderByColumn(editColumnIndex);
195: getResultPreferences().addOrderByColumn(
196: editColumnIndex + moveDelta, info);
197: } catch (FxRuntimeException e) {
198: new FxFacesMsgErr("ResultPreferences.err.moveRow", e)
199: .addToContext();
200: }
201: }
202:
203: public void addOrderByProperty(ActionEvent event) {
204: getResultPreferences().addOrderByColumn(
205: new ResultOrderByInfo(Table.CONTENT, addOrderByName,
206: null, addOrderByDirection));
207: }
208:
209: public void removeOrderByProperty(ActionEvent event) {
210: if (editColumnIndex == -1) {
211: return;
212: }
213: try {
214: getResultPreferences().removeOrderByColumn(editColumnIndex);
215: } catch (FxRuntimeException e) {
216: new FxFacesMsgErr("ResultPreferences.err.removeRow", e)
217: .addToContext();
218: }
219: }
220:
221: public void reloadPreferences(ActionEvent event) {
222: this .resultPreferences = null;
223: }
224:
225: public long getType() {
226: return type;
227: }
228:
229: public void setType(long type) {
230: this .type = type;
231: }
232:
233: public List<SelectItem> getTypes() throws FxApplicationException {
234: if (types == null) {
235: types = new ArrayList<SelectItem>(FxJsfUtils
236: .getManagedBean(SelectBean.class).getTypes());
237: // remove root type
238: for (Iterator<SelectItem> iterator = types.iterator(); iterator
239: .hasNext();) {
240: if (iterator.next().getValue().equals(FxType.ROOT_ID)) {
241: iterator.remove();
242: break;
243: }
244: }
245: types
246: .add(
247: 0,
248: new SelectItem(
249: -1,
250: FxJsfUtils
251: .getLocalizedMessage("ResultPreferences.label.allTypes")));
252: }
253: return types;
254: }
255:
256: public ResultViewType getViewType() {
257: return viewType;
258: }
259:
260: public void setViewType(ResultViewType viewType) {
261: this .viewType = viewType;
262: }
263:
264: public boolean isThumbnails() {
265: return ResultViewType.THUMBNAILS.equals(viewType);
266: }
267:
268: public ResultLocation getLocation() {
269: return location;
270: }
271:
272: public void setLocation(ResultLocation location) {
273: this .location = location;
274: }
275:
276: public String getAddPropertyName() {
277: return addPropertyName;
278: }
279:
280: public void setAddPropertyName(String addPropertyName) {
281: this .addPropertyName = addPropertyName;
282: }
283:
284: public int getEditColumnIndex() {
285: return editColumnIndex;
286: }
287:
288: public void setEditColumnIndex(int editColumnIndex) {
289: this .editColumnIndex = editColumnIndex;
290: }
291:
292: public SortDirection getAddOrderByDirection() {
293: return addOrderByDirection;
294: }
295:
296: public void setAddOrderByDirection(SortDirection addOrderByDirection) {
297: this .addOrderByDirection = addOrderByDirection;
298: }
299:
300: public String getAddOrderByName() {
301: return addOrderByName;
302: }
303:
304: public void setAddOrderByName(String addOrderByName) {
305: this .addOrderByName = addOrderByName;
306: }
307:
308: public boolean isCustomized() throws FxApplicationException {
309: return EJBLookup.getResultPreferencesEngine().isCustomized(
310: type, viewType, location);
311: }
312:
313: public ResultPreferencesEdit getResultPreferences() {
314: if (resultPreferences == null) {
315: try {
316: resultPreferences = EJBLookup
317: .getResultPreferencesEngine().load(type,
318: viewType, location).getEditObject();
319: } catch (FxNotFoundException e) {
320: new FxFacesMsgWarn("ResultPreferences.wng.notFound")
321: .addToContext();
322: resultPreferences = new ResultPreferences()
323: .getEditObject();
324: } catch (FxApplicationException e) {
325: new FxFacesMsgErr("ResultPreferences.err.load", e)
326: .addToContext();
327: }
328: }
329: return resultPreferences;
330: }
331:
332: public List<SelectItem> getProperties() {
333: if (properties == null || cachedTypeId != getType()) {
334: final FxEnvironment environment = CacheAdmin
335: .getFilteredEnvironment();
336: final FxType type = environment
337: .getType(getType() != -1 ? getType()
338: : FxType.ROOT_ID);
339: final List<FxPropertyAssignment> contentProperties = type
340: .getAssignedProperties();
341: properties = new ArrayList<SelectItem>(contentProperties
342: .size() + 10);
343: final MessageBean messageBean = MessageBean.getInstance();
344: // add virtual properties...
345: final SelectItemGroup virtualGroup = new SelectItemGroup(
346: messageBean
347: .getMessage("ResultPreferences.label.group.virtual"));
348: virtualGroup
349: .setSelectItems(new SelectItem[] {
350: new SelectItem(
351: "@pk",
352: messageBean
353: .getMessage("ResultPreferences.label.property.pk")),
354: new SelectItem(
355: "@path",
356: messageBean
357: .getMessage("ResultPreferences.label.property.path")) });
358: properties.add(virtualGroup);
359: // add type properties
360: properties.add(filteredPropertiesGroup(contentProperties,
361: messageBean.getMessage(
362: "ResultPreferences.label.group.type", type
363: .getLabel().getBestTranslation()),
364: false));
365: // add derived properties
366: properties
367: .add(filteredPropertiesGroup(
368: contentProperties,
369: messageBean
370: .getMessage("ResultPreferences.label.group.derived"),
371: true));
372:
373: cachedTypeId = getType();
374: }
375: return properties;
376: }
377:
378: private SelectItemGroup filteredPropertiesGroup(
379: List<FxPropertyAssignment> contentProperties, String title,
380: boolean includeDerived) {
381: final SelectItemGroup group = new SelectItemGroup(title);
382: final List<SelectItem> properties = new ArrayList<SelectItem>();
383: for (FxPropertyAssignment assignment : contentProperties) {
384: if (includeDerived
385: && assignment.isDerivedAssignment()
386: || (!includeDerived && !assignment
387: .isDerivedAssignment())) {
388: properties.add(new SelectItem(assignment.getProperty()
389: .getName(), assignment.getProperty().getLabel()
390: .getBestTranslation()));
391: }
392: }
393: // sort by label
394: Collections.sort(properties, new FxJsfUtils.SelectItemSorter());
395: group.setSelectItems(properties
396: .toArray(new SelectItem[properties.size()]));
397: return group;
398: }
399:
400: public List<SelectItem> getSelectedProperties() {
401: // caching this is not trivial because the selectedColumns list
402: // is updated between phases by the datatable
403: final FxEnvironment environment = CacheAdmin
404: .getFilteredEnvironment();
405: final List<ResultColumnInfo> columns;
406: if (JsfPhaseListener.isInPhase(PhaseId.PROCESS_VALIDATIONS)) {
407: //noinspection unchecked
408: columns = (List) ((WrappedHtmlDataTable) getSelectedColumnsTable())
409: .getDataModel().getWrappedData();
410: } else {
411: columns = getResultPreferences().getSelectedColumns();
412: }
413: List<SelectItem> result = new ArrayList<SelectItem>(columns
414: .size());
415: for (ResultColumnInfo info : columns) {
416: result.add(new SelectItem(info.getPropertyName(), info
417: .getLabel(environment)));
418: }
419: return result;
420: }
421:
422: public HtmlDataTable getSelectedColumnsTable() {
423: if (selectedColumnsTable == null) {
424: selectedColumnsTable = new WrappedHtmlDataTable();
425: } else {
426: UIComponent parent = selectedColumnsTable.getParent();
427: while (parent.getParent() != null) {
428: parent = parent.getParent();
429: }
430: if (parent instanceof UIViewRoot
431: && parent != FacesContext.getCurrentInstance()
432: .getViewRoot()) {
433: // create new table when view root changes
434: System.out
435: .println("View root changed - creating new wrapped table.");
436: selectedColumnsTable = new WrappedHtmlDataTable();
437: }
438: }
439: return selectedColumnsTable;
440: }
441:
442: public void setSelectedColumnsTable(
443: HtmlDataTable selectedColumnsTable) {
444: this .selectedColumnsTable = (WrappedHtmlDataTable) selectedColumnsTable;
445: }
446:
447: /**
448: * Provides the property labels for the result preferences page, including virtual properties like @pk.
449: *
450: * @return the property labels for the result preferences page, including virtual properties like @pk.
451: */
452: public Map<String, String> getPropertyLabelMap() {
453: if (propertyLabelMap == null) {
454: propertyLabelMap = FxSharedUtils
455: .getMappedFunction(new FxSharedUtils.ParameterMapper<String, String>() {
456: private FxEnvironment environment = CacheAdmin
457: .getFilteredEnvironment();
458:
459: public String get(Object key) {
460: if (key == null) {
461: return null;
462: }
463: final String name = key.toString();
464: if ("@pk".equals(name)) {
465: return MessageBean
466: .getInstance()
467: .getMessage(
468: "ResultPreferences.label.property.pk");
469: } else if ("@path".equals(name)) {
470: return MessageBean
471: .getInstance()
472: .getMessage(
473: "ResultPreferences.label.property.path");
474: } else {
475: return environment.getProperty(name)
476: .getLabel()
477: .getBestTranslation();
478: }
479: }
480: });
481: }
482: return propertyLabelMap;
483: }
484: }
|