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.jsfsupport.container;
042:
043: import java.sql.*;
044: import java.util.*;
045: import javax.faces.*;
046: import javax.faces.el.*;
047: import javax.faces.model.*;
048:
049: //!JOE This *was* a copy of com.sun.jsfcl.data.ResultSetPropertyResolver - but now it contains only
050: //!JOE design-time behavior, and is no longer similar... This must stay.
051:
052: /**
053: * This custom Property Resolver handles the special case of resolving ResultSet columns into
054: * editable data values. This also enables binding to a SelectItem array from a ResultSet for
055: * filling lists and dropdowns.
056: *
057: * These expressions are supported:
058: *
059: * #{...myResultSet.currentRow.COLUMN_NAME}
060: * --> binds to the 'COLUMN_NAME' column of the current row of the ResultSet
061: *
062: * #(...myResultSet.selectItems['COLUMN_NAME'])
063: * #(...myResultSet.selectItems['VALUE_COLUMN_NAME,LABEL_COLUMN_NAME'])
064: * #(...myResultSet.selectItems['VALUE_COLUMN_NAME,LABEL_COLUMN_NAME,DESC_COLUMN_NAME'])
065: * --> binds to an array of SelectItem generated by iterating through the ResultSet
066: */
067: public class ResultSetPropertyResolver extends PropertyResolver {
068:
069: public static final String CURRENT_ROW_KEY = "currentRow"; // NOI18N
070: public static final String SELECT_ITEMS_KEY = "selectItems"; // NOI18N
071:
072: protected PropertyResolver nested;
073:
074: public ResultSetPropertyResolver(PropertyResolver nested) {
075: this .nested = nested;
076: }
077:
078: public Object getValue(Object base, Object property)
079: throws EvaluationException, PropertyNotFoundException {
080: // System.out.println("ResultSetPropertyResolver.get([" + base + "], [" + property + "]) -->");
081: if (base instanceof ResultSet) {
082: if (CURRENT_ROW_KEY.equals(property)) {
083: Object o = new RowData((ResultSet) base);
084: // System.out.println(" return [" + o + "]");
085: return o;
086: }
087: if (SELECT_ITEMS_KEY.equals(property)) {
088: Object o = new ColumnData((ResultSet) base);
089: // System.out.println(" return [" + o + "]");
090: return o;
091: }
092: } else if (base instanceof RowData) {
093: Object o = ((RowData) base).getData(property.toString());
094: // System.out.println(" return [" + o + "]");
095: return o;
096: } else if (base instanceof ColumnData) {
097: Object o = ((ColumnData) base).getSelectItems(property
098: .toString());
099: // System.out.println(" return [" + o + "]");
100: return o;
101: }
102: // System.out.println(" (deferring to nested)");
103: Object o = nested.getValue(base, property);
104: // if (o instanceof DesignBean && ((DesignBean)o).getInstance() instanceof ResultSet) {
105: // initResultSet((ResultSet)((DesignBean)o).getInstance());
106: // }
107: // else if (o instanceof ResultSet) {
108: // initResultSet((ResultSet)o);
109: // }
110: // System.out.println(" return [" + o + "]");
111: return o;
112: }
113:
114: public Object getValue(Object base, int index)
115: throws EvaluationException, PropertyNotFoundException {
116: Object o = nested.getValue(base, index);
117: // if (o instanceof ResultSet) {
118: // initResultSet((ResultSet)o);
119: // }
120: return o;
121: }
122:
123: public void setValue(Object base, Object property, Object value)
124: throws EvaluationException, PropertyNotFoundException {
125: if (base instanceof RowData) {
126: ((RowData) base).setData(property.toString(), value);
127: return;
128: }
129: nested.setValue(base, property, value);
130: }
131:
132: public void setValue(Object base, int index, Object value)
133: throws EvaluationException, PropertyNotFoundException {
134: nested.setValue(base, index, value);
135: }
136:
137: public boolean isReadOnly(Object base, Object property)
138: throws EvaluationException, PropertyNotFoundException {
139: if (base instanceof ResultSet
140: && (CURRENT_ROW_KEY.equals(property) || SELECT_ITEMS_KEY
141: .equals(property))) {
142: return true;
143: } else if (base instanceof RowData) {
144: return false;
145: } else if (base instanceof ColumnData) {
146: return true;
147: }
148: return nested.isReadOnly(base, property);
149: }
150:
151: public boolean isReadOnly(Object base, int index)
152: throws EvaluationException, PropertyNotFoundException {
153: return nested.isReadOnly(base, index);
154: }
155:
156: public Class getType(Object base, Object property)
157: throws EvaluationException, PropertyNotFoundException {
158: if (base instanceof ResultSet) {
159: if (CURRENT_ROW_KEY.equals(property)) {
160: return RowData.class;
161: }
162: if (SELECT_ITEMS_KEY.equals(property)) {
163: return ColumnData.class;
164: }
165: } else if (base instanceof RowData) {
166: return ((RowData) base).getDataType(property.toString());
167: } else if (base instanceof ColumnData) {
168: return ArrayList.class;
169: }
170: return nested.getType(base, property);
171: }
172:
173: public Class getType(Object base, int index)
174: throws EvaluationException, PropertyNotFoundException {
175: return nested.getType(base, index);
176: }
177:
178: ////////////////////////////////////////////////////////////////////////////////////////////////
179: ////////////////////////////////////////////////////////////////////////////////////////////////
180:
181: public class RowData {
182:
183: protected ResultSet resultSet;
184: protected ResultSetMetaData metadata;
185: protected ArrayList columnNameList;
186:
187: public RowData(ResultSet resultSet) {
188: this .resultSet = resultSet;
189: try {
190: metadata = resultSet.getMetaData();
191: columnNameList = new ArrayList();
192: int cols = metadata.getColumnCount();
193: for (int i = 1; i <= cols; i++) {
194: columnNameList.add(metadata.getColumnName(i));
195: }
196: } catch (SQLException x) {
197: throw new FacesException(x);
198: }
199: }
200:
201: public Class getDataType(String column)
202: throws PropertyNotFoundException {
203: if (!columnNameList.contains(column)) {
204: throw new PropertyNotFoundException(
205: "Invalid column name: " + column);
206: }
207: try {
208: return Class.forName(metadata
209: .getColumnClassName(columnNameList
210: .indexOf(column) + 1));
211: } catch (Exception x) {
212: return null;
213: }
214: }
215:
216: public Object getData(String column)
217: throws PropertyNotFoundException {
218: if (!columnNameList.contains(column)) {
219: throw new PropertyNotFoundException(
220: "Invalid column name: " + column);
221: }
222: try {
223: // if (Beans.isDesignTime()) {
224: return getFakeData(metadata, column);
225: // }
226: // else {
227: // initResultSet(resultSet);
228: // return resultSet.getObject(column);
229: // }
230: } catch (SQLException e) {
231: throw new FacesException(e);
232: }
233: }
234:
235: public Object setData(String column, Object value)
236: throws PropertyNotFoundException {
237: if (!columnNameList.contains(column)) {
238: throw new PropertyNotFoundException(
239: "Invalid column name: " + column);
240: }
241: try {
242: Object previous;
243: // if (!Beans.isDesignTime()) {
244: // initResultSet(resultSet);
245: // previous = resultSet.getObject(column);
246: // if ((previous == null) && (value == null)) {
247: // return previous;
248: // }
249: // else if ((previous != null) && (value != null) &&
250: // previous.equals(value)) {
251: // return previous;
252: // }
253: // resultSet.updateObject(column, value);
254: // return previous;
255: // }
256: // else {
257: previous = getFakeData(metadata, column);
258: return previous;
259: // }
260: } catch (SQLException e) {
261: throw new FacesException(e);
262: }
263: }
264: }
265:
266: ////////////////////////////////////////////////////////////////////////////////////////////////
267: ////////////////////////////////////////////////////////////////////////////////////////////////
268:
269: public class ColumnData {
270: protected ResultSet resultSet;
271: protected ResultSetMetaData metadata;
272:
273: public ColumnData(ResultSet resultSet) {
274: this .resultSet = resultSet;
275: try {
276: this .metadata = resultSet.getMetaData();
277: } catch (SQLException x) {
278: throw new FacesException(x);
279: }
280: }
281:
282: public Object getSelectItems(String columns) {
283: /*
284: * returns a List of Objects or SelectItems
285: *
286: * (examples based on PERSON database table):
287: *
288: * "NAME" -->
289: * returns a List filled with SelectItem objects,
290: * with the 'itemValue' set to NAME's values
291: *
292: * "PERSONID,NAME" -->
293: * returns a List filled with SelectItem objects,
294: * with the 'itemValue' set to PERSONID's values,
295: * and the 'itemLabel' set to NAME's values
296: *
297: * "PERSONID,NAME,JOBTITLE" -->
298: * returns a List filled with SelectItem objects,
299: * with the 'itemValue' set to PERSONID's values,
300: * the 'itemLabel' set to NAME's values,
301: * and the 'itemDescription' set to JOBTITLE's values
302: *
303: * Any cases that are out-of-scope throw IllegalArgumentException
304: */
305: String itemValueName = null;
306: String itemLabelName = null;
307: String itemDescriptionName = null;
308:
309: //MBOHM fix 5086833
310: //could have internal commas, in say, selectItems['employee.employeeid, employee.firstname || \' , \' || employee.lastname']
311: List cols = new ArrayList();
312: String col;
313: boolean quoteOpen = false;
314: int currStart = 0;
315: for (int i = 0; i < columns.length(); i++) {
316: char c = columns.charAt(i);
317: if (c == '\'') {
318: quoteOpen = !quoteOpen;
319: } else if (c == ',' && !quoteOpen) {
320: col = columns.substring(currStart, i);
321: if (col.length() > 0) {
322: cols.add(col);
323: }
324: currStart = i + 1;
325: }
326: }
327: //get the remaining stuff after the last period
328: if (currStart < columns.length()) {
329: col = columns.substring(currStart);
330: cols.add(col);
331: }
332:
333: //String[] args = columns.split(","); //NOI18N
334: String[] args = (String[]) cols.toArray(new String[cols
335: .size()]);
336: if (args.length < 1) {
337: throw new IllegalArgumentException();
338: }
339: itemValueName = args[0];
340: if (args.length > 1) {
341: itemLabelName = args[1];
342: }
343: if (args.length > 2) {
344: itemDescriptionName = args[2];
345: }
346:
347: ArrayList list = new ArrayList();
348: // if (!Beans.isDesignTime()) {
349: // try {
350: // initResultSet(resultSet);
351: // int resultSetIndexSave = resultSet.getRow();
352: // resultSet.first();
353: // while (!resultSet.isAfterLast()) {
354: // if (itemLabelName == null) {
355: // list.add(new SelectItem(
356: // resultSet.getObject(itemValueName)
357: // ));
358: // }
359: // else if (itemDescriptionName == null) {
360: // list.add(new SelectItem(
361: // resultSet.getObject(itemValueName),
362: // resultSet.getObject(itemLabelName).toString()
363: // ));
364: // }
365: // else {
366: // list.add(new SelectItem(
367: // resultSet.getObject(itemValueName),
368: // resultSet.getObject(itemLabelName).toString(),
369: // resultSet.getObject(itemDescriptionName).toString()
370: // ));
371: // }
372: // resultSet.next();
373: // }
374: // if (resultSetIndexSave > 0) {
375: // resultSet.absolute(resultSetIndexSave);
376: // }
377: // else {
378: // resultSet.first();
379: // }
380: // }
381: // catch (SQLException x) {
382: // x.printStackTrace();
383: // }
384: // }
385: // else {
386: for (int i = 0; i < 3; i++) {
387: try {
388: if (itemLabelName == null) {
389: list.add(new SelectItem(getFakeData(metadata,
390: itemValueName)));
391: } else if (itemDescriptionName == null) {
392: list.add(new SelectItem(getFakeData(metadata,
393: itemValueName), getFakeData(metadata,
394: itemLabelName).toString()));
395: } else {
396: list.add(new SelectItem(getFakeData(metadata,
397: itemValueName), getFakeData(metadata,
398: itemLabelName).toString(), getFakeData(
399: metadata, itemDescriptionName)
400: .toString()));
401: }
402: } catch (SQLException x) {
403: }
404: }
405: // }
406:
407: return list;
408: }
409:
410: }
411:
412: ////////////////////////////////////////////////////////////////////////////////////////////////
413: ////////////////////////////////////////////////////////////////////////////////////////////////
414:
415: //!JOE - this code has been removed, because we never need to execute the rowset at design-time, we
416: //!JOE can always use fake data to represent the rows by looking at the meta-data.
417: // public static void initResultSet(ResultSet resultSet) {
418: // try {
419: // if (resultSet.isBeforeFirst()) {
420: // try {
421: // resultSet.first();
422: // }
423: // catch (SQLException x) {
424: // }
425: // }
426: // }
427: // catch (SQLException x) {
428: // if (resultSet instanceof RowSet) {
429: // try {
430: // ((RowSet)resultSet).execute();
431: // resultSet.first();
432: // }
433: // catch (SQLException x2) {
434: // }
435: // }
436: // }
437: // }
438:
439: ////////////////////////////////////////////////////////////////////////////////////////////////
440: ////////////////////////////////////////////////////////////////////////////////////////////////
441:
442: private static Object getFakeData(ResultSetMetaData rsmd,
443: String colName) throws SQLException {
444:
445: int colIndex = -1;
446: for (int i = 1; i <= rsmd.getColumnCount(); i++) {
447: if (rsmd.getColumnName(i).equals(colName)) {
448: colIndex = i;
449: break;
450: }
451: }
452: switch (rsmd.getColumnType(colIndex)) {
453: case Types.ARRAY:
454: return new java.sql.Array() {
455: public Object getArray() {
456: return null;
457: }
458:
459: public Object getArray(long index, int count) {
460: return null;
461: }
462:
463: public Object getArray(long index, int count, Map map) {
464: return null;
465: }
466:
467: public Object getArray(Map map) {
468: return null;
469: }
470:
471: public int getBaseType() {
472: return Types.CHAR;
473: }
474:
475: public String getBaseTypeName() {
476: return "CHAR";
477: }
478:
479: public ResultSet getResultSet() {
480: return null;
481: }
482:
483: public ResultSet getResultSet(long index, int count) {
484: return null;
485: }
486:
487: public ResultSet getResultSet(long index, int count,
488: Map map) {
489: return null;
490: }
491:
492: public ResultSet getResultSet(Map map) {
493: return null;
494: }
495:
496: public void free() {
497: }
498: };
499: case Types.BIGINT:
500:
501: //return new Long(rowIndex);
502: return new Long(123);
503: case Types.BINARY:
504: return new byte[] { 1, 2, 3, 4, 5 };
505: case Types.BIT:
506: return new Boolean(true);
507: case Types.BLOB:
508: return new javax.sql.rowset.serial.SerialBlob(new byte[] {
509: 1, 2, 3, 4, 5 });
510: case Types.BOOLEAN:
511: return new Boolean(true);
512: case Types.CHAR:
513:
514: //return new String(colName + rowIndex);
515: return new String("abc");
516: case Types.CLOB:
517: return new javax.sql.rowset.serial.SerialClob(
518: "arbitraryClobData".toCharArray());
519: case Types.DATALINK:
520: try {
521: return new java.net.URL("http://www.sun.com");
522: } catch (java.net.MalformedURLException e) {
523: return null;
524: }
525: case Types.DATE:
526: return new java.sql.Date(new java.util.Date().getTime());
527: case Types.DECIMAL:
528: return new java.math.BigDecimal(java.math.BigInteger.ONE);
529: case Types.DISTINCT:
530: return null;
531: case Types.DOUBLE:
532:
533: //return new Double(rowIndex);
534: return new Double(123);
535: case Types.FLOAT:
536:
537: //return new Double(rowIndex);
538: return new Double(123);
539: case Types.INTEGER:
540:
541: //return new Integer(rowIndex);
542: return new Integer(123);
543: case Types.JAVA_OBJECT:
544:
545: //return new String(colName + "_" + rowIndex);
546: return new String("abc");
547: case Types.LONGVARBINARY:
548: return new byte[] { 1, 2, 3, 4, 5 };
549: case Types.LONGVARCHAR:
550:
551: //return new String(colName + "_" + rowIndex);
552: return new String("abc");
553: case Types.NULL:
554: return null;
555: case Types.NUMERIC:
556: return new java.math.BigDecimal(java.math.BigInteger.ONE);
557: case Types.OTHER:
558: return null;
559: case Types.REAL:
560:
561: //return new Float(rowIndex);
562: return new Float(123);
563: case Types.REF:
564: return new java.sql.Ref() {
565: private Object data = new String("abc");
566:
567: public String getBaseTypeName() {
568: return "CHAR";
569: }
570:
571: public Object getObject() {
572: return data;
573: }
574:
575: public Object getObject(Map map) {
576: return data;
577: }
578:
579: public void setObject(Object value) {
580: data = value;
581: }
582: };
583: case Types.SMALLINT:
584:
585: //return new Short((short)rowIndex);
586: return new Short((short) 123);
587: case Types.STRUCT:
588: return new java.sql.Struct() {
589: private String[] data = { "abc", "def", "ghi" };
590:
591: public Object[] getAttributes() {
592: return data;
593: }
594:
595: public Object[] getAttributes(Map map) {
596: return data;
597: }
598:
599: public String getSQLTypeName() {
600: return "CHAR";
601: }
602: };
603: case Types.TIME:
604: return new java.sql.Time(new java.util.Date().getTime());
605: case Types.TIMESTAMP:
606: return new java.sql.Timestamp(new java.util.Date()
607: .getTime());
608: case Types.TINYINT:
609:
610: //return new Byte((byte)rowIndex);
611: return new Byte((byte) 123);
612: case Types.VARBINARY:
613: return new byte[] { 1, 2, 3, 4, 5 };
614: case Types.VARCHAR:
615:
616: //return new String(colName + "_" + rowIndex);
617: return new String("abc");
618: }
619: return null;
620: }
621: }
|