001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.visualweb.web.ui.dt.component.table;
042:
043: import com.sun.data.provider.FieldKey;
044: import com.sun.data.provider.TableDataProvider;
045: import com.sun.data.provider.impl.ObjectArrayDataProvider;
046: import com.sun.data.provider.impl.ObjectListDataProvider;
047: import com.sun.rave.designtime.DesignBean;
048: import com.sun.rave.designtime.DesignContext;
049: import com.sun.rave.designtime.DesignProject;
050: import com.sun.rave.designtime.DesignProperty;
051: import com.sun.rave.designtime.Position;
052: import com.sun.rave.designtime.ext.DesignBeanExt;
053: import com.sun.rave.designtime.faces.FacesDesignContext;
054: import com.sun.rave.designtime.faces.FacesDesignProject;
055: import com.sun.rave.web.ui.component.Checkbox;
056: import com.sun.rave.web.ui.component.TableColumn;
057: import java.lang.reflect.Type;
058: import java.util.ArrayList;
059: import java.util.HashMap;
060: import java.util.List;
061: import java.util.Map;
062: import java.util.ResourceBundle;
063: import java.util.Vector;
064: import org.openide.ErrorManager;
065: import org.openide.util.Exceptions;
066:
067: /**
068: * This class defines the design time state of the Table Group Component
069: *
070: * @author Winston Prakash
071: */
072: public class TableRowGroupDesignState {
073:
074: private ResourceBundle bundle = ResourceBundle
075: .getBundle(TableRowGroupDesignState.class.getPackage()
076: .getName()
077: + ".Bundle");
078:
079: private static final String MODEL_INSTANCE_NAME_SUFFIX = "DefaultModel"; //NOI18N
080:
081: private static final String SOURCE_DATA_PROPERTY = "sourceData";
082: private static final String SOURCE_VARIABLE_PROPERTY = "sourceVar";
083: private static final String ROWS_PROPERTY = "rows";
084: private static final String EMPTY_DATA_MSG_PROPERTY = "emptyDataMsg";
085: private static final String PAGINATED_PROPERTY = "paginated";
086:
087: private DesignBean tableRowGroupBean = null;
088:
089: FacesDesignContext fcontext = null;
090:
091: public static final String sourceVarNameBase = "currentRow"; //NOI18N
092: private String sourceVarName = sourceVarNameBase;
093:
094: private Map selectedColumnsDesignStates = new HashMap();
095:
096: private Vector selectedColumnNames = new Vector();
097: private Vector availableColumnNames = new Vector();
098:
099: private TableDataProvider tableDataProvider;
100: private DesignBean dataProviderBean = null;
101:
102: private int paginationRows = 10;
103: private String emptyDataMsg = null;
104:
105: private boolean childBeansDeleted = false;
106: private boolean rowGroupPaginated = false;
107:
108: private boolean dataProviderReset = false;
109:
110: private static int varCount = 0;
111:
112: private List sourceVariableList = new ArrayList();
113:
114: /** Creates a new instance of TableDesignState */
115: public TableRowGroupDesignState(DesignBean tblGrpBean) {
116: tableRowGroupBean = tblGrpBean;
117: fcontext = (FacesDesignContext) tableRowGroupBean
118: .getDesignContext();
119: }
120:
121: /**
122: * Set the selected column names
123: */
124: public void setSelectedColumnNames(Vector selectedColNames) {
125: selectedColumnNames = selectedColNames;
126: }
127:
128: /**
129: * Get the selected column names
130: */
131: public Vector getSelectedColumnNames() {
132: return selectedColumnNames;
133: }
134:
135: /**
136: * Set the available column names
137: */
138: public void setAvailableColumnNames(Vector availColNames) {
139: availableColumnNames = availColNames;
140: }
141:
142: /**
143: * Get the available column names
144: */
145: public Vector getAvailableColumnNames() {
146: return availableColumnNames;
147: }
148:
149: /**
150: * Set the Table column design states
151: */
152: public void setColumnDesignStates(Map colDesignStates) {
153: selectedColumnsDesignStates = colDesignStates;
154: }
155:
156: /**
157: * Get the Table column design states
158: */
159: public Map getColumnDesignStates() {
160: return selectedColumnsDesignStates;
161: }
162:
163: /**
164: * Get the associated Data Model Bean
165: */
166: public DesignBean getDataProviderBean() {
167: return dataProviderBean;
168: }
169:
170: /**
171: * Set the Data model DesignBeean to this design state
172: */
173: public void setDataProviderBean(DesignBean modelBean) {
174: setDataProviderBean(modelBean, true);
175: }
176:
177: /**
178: * Set the Data model DesignBeean to this design state
179: * Force the selected columns names with all columns from the Data model
180: */
181: public void setDataProviderBean(DesignBean modelBean,
182: boolean resetColumns) {
183:
184: if (modelBean != dataProviderBean) {
185: if (modelBean.getInstance() instanceof TableDataProvider) {
186: tableDataProvider = (TableDataProvider) modelBean
187: .getInstance();
188: } else if (List.class.isAssignableFrom(modelBean
189: .getBeanInfo().getBeanDescriptor().getBeanClass())) {
190: List listObject = (List) modelBean.getInstance();
191: if (listObject == null) {
192: listObject = new ArrayList();
193: }
194: tableDataProvider = new ObjectListDataProvider(
195: listObject);
196: if (modelBean instanceof DesignBeanExt) {
197: try {
198: java.lang.reflect.Type[] parameterTypes = ((com.sun.rave.designtime.ext.DesignBeanExt) modelBean)
199: .getTypeParameters();
200: if (parameterTypes != null
201: && (parameterTypes.length > 0)) {
202: ((com.sun.data.provider.impl.ObjectListDataProvider) tableDataProvider)
203: .setObjectType((java.lang.Class) parameterTypes[0]);
204: }
205: } catch (ClassNotFoundException exc) {
206: ErrorManager.getDefault().notify(exc);
207: }
208: }
209: } else if (modelBean.getInstance() instanceof Object[]) {
210: tableDataProvider = new ObjectArrayDataProvider(
211: (Object[]) modelBean.getInstance());
212: } else {
213: throw new IllegalArgumentException(dataProviderBean
214: .getInstanceName()
215: + bundle.getString("NOT_DATA_PROVIDER"));
216: }
217:
218: FieldKey[] columns = tableDataProvider.getFieldKeys();
219: if ((columns == null) || (columns.length == 0)) {
220: return;
221: }
222:
223: // OK new Table Data Provider is added. Remove all old columns
224: DesignBean[] children = tableRowGroupBean.getChildBeans();
225: for (int i = 0; i < children.length; i++) {
226: fcontext.deleteBean(children[i]);
227: }
228: childBeansDeleted = true;
229: } else {
230: childBeansDeleted = false;
231: }
232:
233: dataProviderBean = modelBean;
234:
235: if (resetColumns) {
236: resetTableColumns();
237: }
238: }
239:
240: public void loadState() {
241:
242: // Load the model bean.
243: loadModelBean();
244:
245: if (!dataProviderReset) {
246: Map dpFields = new HashMap();
247:
248: try {
249: FieldKey[] columns = tableDataProvider.getFieldKeys();
250: if ((columns != null) && (columns.length > 0)) {
251: for (int i = 0; i < columns.length; i++) {
252: //Skip FieldKey of type "Class" - 6309491
253: if (tableDataProvider.getType(columns[i])
254: .toString().indexOf("java.lang.Class") == -1) {
255: dpFields.put(columns[i].getDisplayName(),
256: columns[i]);
257: }
258: }
259: }
260: } catch (Exception exc) {
261: exc.printStackTrace();
262: }
263: loadSourceVariable();
264: // Load the child state from the TableColumn
265: int childCount = tableRowGroupBean.getChildBeanCount();
266: for (int i = 0; i < childCount; i++) {
267: DesignBean tblColumndBean = tableRowGroupBean
268: .getChildBean(i);
269: if (tblColumndBean.getInstance() instanceof TableColumn) {
270: TableColumnDesignState tblColDesignState = new TableColumnDesignState(
271: tblColumndBean);
272: tblColDesignState.loadState();
273: // If the Column has been removed from the CachedRowsetDataProvider change designstates name to
274: // TableColumnBean instance name and the data binding too and set the child type as Static Text
275: // Reset only if the Table Column is bound to this Table Data Provider
276: /*if(!dpFields.contains(tblColDesignState.getName()) &&
277: (tblColDesignState.getValueExpression().indexOf(sourceVarName) != -1)){
278: tblColDesignState.setName(tblColumndBean.getInstanceName());
279: tblColDesignState.setHeader(tblColumndBean.getInstanceName());
280: tblColDesignState.setType(StaticText.class);
281: tblColDesignState.setValueExpression(ResourceBundle.getBundle("com/sun/webui/jsf/component/table/Bundle").getString("STATIC_TEXT_LBL"));
282: }*/
283: if (dpFields.keySet().contains(
284: tblColDesignState.getName())) {
285: FieldKey column = (FieldKey) dpFields
286: .get(tblColDesignState.getName());
287: tblColDesignState
288: .setColumnType(tableDataProvider
289: .getType(column));
290: }
291: selectedColumnsDesignStates.put(tblColDesignState
292: .getName(), tblColDesignState);
293: selectedColumnNames
294: .add(tblColDesignState.getName());
295: }
296: }
297: }
298:
299: paginationRows = getIntegerPropertyValue(ROWS_PROPERTY);
300: if (paginationRows == 0)
301: paginationRows = 10;
302: emptyDataMsg = getStringPropertyValue(EMPTY_DATA_MSG_PROPERTY);
303: }
304:
305: /**
306: * Load the source variable. Even the Row Group gets new Data Provider
307: * the old source variable name should be preserved
308: */
309: public void loadSourceVariable() {
310: sourceVarName = getStringPropertyValue(SOURCE_VARIABLE_PROPERTY);
311: }
312:
313: // For performance improvement. No need to get all the contexts in the project
314: // Bug Fix: 6422729
315: private DesignContext[] getDesignContexts(DesignBean designBean) {
316: DesignProject designProject = designBean.getDesignContext()
317: .getProject();
318: DesignContext[] contexts;
319: if (designProject instanceof FacesDesignProject) {
320: contexts = ((FacesDesignProject) designProject)
321: .findDesignContexts(new String[] { "request",
322: "session", "application" });
323: } else {
324: contexts = new DesignContext[0];
325: }
326: DesignContext[] designContexts = new DesignContext[contexts.length + 1];
327: designContexts[0] = designBean.getDesignContext();
328: System.arraycopy(contexts, 0, designContexts, 1,
329: contexts.length);
330: return designContexts;
331: }
332:
333: /**
334: * Load the model bean from the TableRowGroup bean from the source data tag.
335: * If not found create or get the default model bean from the context
336: */
337: private void loadModelBean() {
338:
339: String sourceDataStr = getPropertyValueSource(SOURCE_DATA_PROPERTY);
340: if (sourceDataStr != null) {
341: //DesignContext[] contexts = fcontext.getProject().getDesignContexts();
342: DesignContext[] contexts = getDesignContexts(tableRowGroupBean);
343:
344: for (int i = 0; i < contexts.length; i++) {
345: DesignBean[] dpModelBeans = contexts[i]
346: .getBeansOfType(TableDataProvider.class);
347: for (int j = 0; j < dpModelBeans.length; j++) {
348: String modelBindingExpr = ((FacesDesignContext) contexts[i])
349: .getBindingExpr(dpModelBeans[j]);
350: if (sourceDataStr.startsWith(modelBindingExpr)) {
351: dataProviderBean = dpModelBeans[j];
352: tableDataProvider = (TableDataProvider) dataProviderBean
353: .getInstance();
354: break;
355: }
356: }
357:
358: DesignBean[] listModelBeans = contexts[i]
359: .getBeansOfType(List.class);
360: for (int j = 0; j < listModelBeans.length; j++) {
361: String modelBindingExpr = ((FacesDesignContext) contexts[i])
362: .getBindingExpr(listModelBeans[j]);
363: if (sourceDataStr.startsWith(modelBindingExpr)) {
364: dataProviderBean = listModelBeans[j];
365: List listObject = (List) dataProviderBean
366: .getInstance();
367: if (listObject == null) {
368: listObject = new ArrayList();
369: }
370: tableDataProvider = new ObjectListDataProvider(
371: listObject);
372: if (dataProviderBean instanceof DesignBeanExt) {
373: try {
374: java.lang.reflect.Type[] parameterTypes = ((com.sun.rave.designtime.ext.DesignBeanExt) dataProviderBean)
375: .getTypeParameters();
376: if (parameterTypes != null
377: && (parameterTypes.length > 0)) {
378: ((com.sun.data.provider.impl.ObjectListDataProvider) tableDataProvider)
379: .setObjectType((java.lang.Class) parameterTypes[0]);
380: }
381: } catch (ClassNotFoundException ex) {
382: Exceptions.printStackTrace(ex);
383: }
384: }
385:
386: break;
387: }
388: }
389:
390: DesignBean[] arrayModelBeans = contexts[i]
391: .getBeansOfType(Object[].class);
392: for (int j = 0; j < arrayModelBeans.length; j++) {
393: String modelBindingExpr = ((FacesDesignContext) contexts[i])
394: .getBindingExpr(arrayModelBeans[j]);
395: if (sourceDataStr.startsWith(modelBindingExpr)) {
396: dataProviderBean = arrayModelBeans[j];
397: tableDataProvider = new ObjectArrayDataProvider(
398: (Object[]) dataProviderBean
399: .getInstance());
400: break;
401: }
402: }
403: }
404: }
405: // XXX - What should we do if the user deleteds the source data?
406: if (dataProviderBean == null) {
407: dataProviderBean = TableDesignHelper
408: .createDefaultDataProvider(tableRowGroupBean
409: .getBeanParent());
410: tableDataProvider = (TableDataProvider) dataProviderBean
411: .getInstance();
412: resetTableColumns();
413: dataProviderReset = true;
414: }
415:
416: }
417:
418: private void resetTableColumns() {
419: // Set the selected column names from the default data model
420: FieldKey[] columns = tableDataProvider.getFieldKeys();
421:
422: if ((columns != null) && (columns.length > 0)) {
423: for (int i = 0; i < columns.length; i++) {
424: selectedColumnNames.add(columns[i].getDisplayName());
425: TableColumnDesignState tblColDesignState = new TableColumnDesignState(
426: columns[i].getDisplayName());
427: tblColDesignState.setColumnType(tableDataProvider
428: .getType(columns[i]));
429: if (tableDataProvider.getType(columns[i])
430: .isAssignableFrom(Boolean.class)) {
431: tblColDesignState.setChildType(Checkbox.class);
432: }
433: selectedColumnsDesignStates.put(tblColDesignState
434: .getName(), tblColDesignState);
435: }
436: }
437: }
438:
439: /**
440: * Clear all the property values set to this state
441: */
442: public void clearProperties() {
443: paginationRows = 5;
444: }
445:
446: /**
447: * Get the boolean value of the property
448: */
449: public boolean getBooleanPropertyValue(String propertyname) {
450: boolean value = false;
451: Object propValue = getPropertyValue(propertyname);
452: if (propValue != null) {
453: value = ((Boolean) propValue).booleanValue();
454: }
455: return value;
456: }
457:
458: /**
459: * Get String property value
460: */
461: private String getStringPropertyValue(String propertyname) {
462: Object value = getPropertyValue(propertyname);
463: if (value != null) {
464: return value.toString();
465: } else {
466: return null;
467: }
468: }
469:
470: /**
471: * Get int property value
472: */
473: private int getIntegerPropertyValue(String propertyname) {
474: Object value = getPropertyValue(propertyname);
475: if (value != null) {
476: return ((Integer) value).intValue();
477: } else {
478: return -1;
479: }
480: }
481:
482: /**
483: * Load the property value from the bean to this state
484: */
485: private Object getPropertyValue(String propertyname) {
486: Object propertyValue = null;
487: DesignProperty designProperty = tableRowGroupBean
488: .getProperty(propertyname);
489: if (designProperty != null) {
490: if (designProperty.getValue() != null) {
491: propertyValue = designProperty.getValue();
492: }
493: }
494: return propertyValue;
495: }
496:
497: /**
498: * Get the property value source from the bean to this state
499: */
500: private String getPropertyValueSource(String propertyname) {
501: String propertyValue = null;
502: DesignProperty designProperty = tableRowGroupBean
503: .getProperty(propertyname);
504: if (designProperty != null) {
505: propertyValue = designProperty.getValueSource();
506: }
507: return propertyValue;
508: }
509:
510: /**
511: * Set the value to the bean property as stored in this state
512: */
513: private void setPropertyValue(String propertyname, Object value) {
514: if (value != null) {
515: DesignProperty designProperty = tableRowGroupBean
516: .getProperty(propertyname);
517: if (designProperty != null) {
518: Object origValue = getPropertyValue(propertyname);
519: if (value != origValue) {
520: if ((value instanceof String)
521: && value.toString().equals("")) {
522: designProperty.unset();
523: } else {
524: designProperty.setValue(value);
525: }
526: }
527: }
528: }
529: }
530:
531: /**
532: * Set a boolean value to the property
533: */
534: private void setBooleanPropertyValue(String propertyname,
535: boolean value) {
536: DesignProperty designProperty = tableRowGroupBean
537: .getProperty(propertyname);
538: if (designProperty != null) {
539: boolean origValue = getBooleanPropertyValue(propertyname);
540: if (origValue != value) {
541: if (value) {
542: designProperty.setValue(new Boolean(true));
543: } else {
544: designProperty.unset();
545: }
546: }
547: }
548: }
549:
550: /**
551: * Set the empty data message
552: */
553: public void setEmptyDataMsg(String msg) {
554: emptyDataMsg = msg;
555: }
556:
557: /**
558: * Get the empty data message
559: */
560: public String getEmptyDataMsg() {
561: return emptyDataMsg;
562: }
563:
564: /**
565: * Set the paginated property to the table row group
566: */
567: public void setPaginated(boolean paginated) {
568: rowGroupPaginated = paginated;
569: }
570:
571: /**
572: * Get the paginated property to the table row group
573: */
574: public boolean getPaginated() {
575: return rowGroupPaginated;
576: }
577:
578: /**
579: * Set the no of rows used to paginate the table row group
580: */
581: public void setRows(int rows) {
582: paginationRows = rows;
583: }
584:
585: /**
586: * Get the no of rows used to paginate the table row group
587: */
588: public int getRows() {
589: return paginationRows;
590: }
591:
592: /*public int getColumnWidth(int colNo){
593: String colName = (String) selectedColumnNames.get(colNo);
594: TableColumnDesignState columnsDesignState = (TableColumnDesignState) selectedColumnsDesignStates.get(colName);
595: return columnsDesignState.getWidth();
596: }
597:
598: public void setColumnWidth(int colNo, int colWidth){
599: setColumnWidth(colNo, colWidth, false);
600: }
601:
602: public void setColumnWidth(int colNo, int colWidth, boolean immediat){
603: String colName = (String) selectedColumnNames.get(colNo);
604: TableColumnDesignState columnsDesignState = (TableColumnDesignState) selectedColumnsDesignStates.get(colName);
605: columnsDesignState.setWidth(colWidth, immediat);
606: }*/
607:
608: /**
609: * Save the design state of the TableRowGroup component
610: */
611: public void saveState() {
612:
613: if (selectedColumnNames.size() < 1) {
614: return;
615: }
616:
617: String defDataBindingExpr = ((FacesDesignContext) dataProviderBean
618: .getDesignContext()).getBindingExpr(dataProviderBean);
619: setPropertyValue(SOURCE_DATA_PROPERTY, defDataBindingExpr);
620: setPropertyValue(EMPTY_DATA_MSG_PROPERTY, emptyDataMsg);
621: setBooleanPropertyValue(PAGINATED_PROPERTY, rowGroupPaginated);
622:
623: if (sourceVarName == null) {
624: sourceVarName = sourceVarNameBase;
625: }
626:
627: setPropertyValue(SOURCE_VARIABLE_PROPERTY, sourceVarName);
628:
629: try {
630: setPropertyValue(ROWS_PROPERTY, new Integer(paginationRows));
631: } catch (Exception exc) {
632: exc.printStackTrace();
633: }
634:
635: if (dataProviderReset) {
636: // OK new Table Data Provider is reset. Remove all old columns
637: DesignBean[] children = tableRowGroupBean.getChildBeans();
638: for (int i = 0; i < children.length; i++) {
639: fcontext.deleteBean(children[i]);
640: }
641: childBeansDeleted = true;
642: }
643:
644: // Persist the design states of the selected Table Column.
645: // Create the table column bean if not created already.
646: for (int i = 0; i < selectedColumnNames.size(); i++) {
647: // Create the Table Columns, set it to the TableColumnDesignState and save its state
648: TableColumnDesignState tblColDesignState = (TableColumnDesignState) selectedColumnsDesignStates
649: .get(selectedColumnNames.get(i));
650: if ((tblColDesignState.getTableColumnBean() == null)
651: || childBeansDeleted) {
652: DesignBean tableColumnBean = fcontext.createBean(
653: TableColumn.class.getName(), tableRowGroupBean,
654: null);
655: tblColDesignState.setTableColumnBean(tableColumnBean);
656: }
657: tblColDesignState.setSourceVariable(sourceVarName);
658: tblColDesignState.saveState();
659: fcontext.moveBean(tblColDesignState.getTableColumnBean(),
660: tableRowGroupBean, new Position(i));
661: }
662:
663: // Remove only the tabel column design bean. Do not yet
664: // remove the Table Column design states. User must not
665: // have closed the customizer only pressed apply button.
666: for (int i = 0; i < availableColumnNames.size(); i++) {
667: TableColumnDesignState tblColDesignState = (TableColumnDesignState) selectedColumnsDesignStates
668: .get(availableColumnNames.get(i));
669: if (tblColDesignState.getTableColumnBean() != null) {
670: fcontext.deleteBean(tblColDesignState
671: .getTableColumnBean());
672: tblColDesignState.setTableColumnBean(null);
673: }
674: }
675:
676: if (childBeansDeleted)
677: TableDesignHelper.adjustTableWidth(tableRowGroupBean);
678:
679: childBeansDeleted = false;
680:
681: if (!TableDesignHelper.isDefaultDataProvider(tableRowGroupBean
682: .getBeanParent(), dataProviderBean)) {
683: TableDesignHelper
684: .deleteDefaultDataProvider(tableRowGroupBean
685: .getBeanParent());
686: }
687: }
688: }
|