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.faces.dt.std;
042:
043: import org.netbeans.modules.visualweb.faces.dt.HtmlDesignInfoBase;
044: import java.awt.Component;
045: import java.awt.Dimension;
046: import java.awt.GridBagConstraints;
047: import java.awt.GridBagLayout;
048: import java.awt.Insets;
049: import java.awt.event.ItemEvent;
050: import java.awt.event.ItemListener;
051: import java.sql.ResultSetMetaData;
052: import java.util.ArrayList;
053: import java.util.HashMap;
054: import java.util.List;
055: import javax.sql.RowSet;
056: import javax.swing.DefaultListCellRenderer;
057: import javax.swing.DefaultListModel;
058: import javax.swing.JComboBox;
059: import javax.swing.JLabel;
060: import javax.swing.JList;
061: import javax.swing.JPanel;
062: import javax.swing.JScrollPane;
063: import javax.swing.JTextPane;
064: import javax.swing.ListModel;
065: import javax.swing.ListSelectionModel;
066: import javax.swing.UIManager;
067: import javax.swing.event.ListSelectionEvent;
068: import javax.swing.event.ListSelectionListener;
069: import org.netbeans.modules.visualweb.faces.dt.util.ComponentBundle;
070: import com.sun.rave.designtime.Constants;
071: import com.sun.rave.designtime.DesignBean;
072: import com.sun.rave.designtime.DesignContext;
073: import com.sun.rave.designtime.DesignProject;
074: import com.sun.rave.designtime.DesignProperty;
075: import com.sun.rave.designtime.faces.FacesDesignContext;
076: import com.sun.rave.designtime.faces.FacesDesignProject;
077:
078: public class ColumnDataBindingPanel extends JPanel {
079:
080: private static final ComponentBundle bundle = ComponentBundle
081: .getBundle(ColumnDataBindingPanel.class);
082:
083: protected DesignProperty prop;
084: protected ValueBindingPanel vbp;
085: protected ColumnDataBindingCustomizer customizer;
086:
087: protected JLabel rsLabel = new JLabel();
088: protected JComboBox rsCombo = new JComboBox();
089:
090: protected HashMap valListModelHash = new HashMap();
091: protected HashMap dispListModelHash = new HashMap();
092:
093: protected JLabel valueListLabel = new JLabel();
094: protected JList valueList = new JList();
095: protected JScrollPane valueListScroll = new JScrollPane(valueList);
096:
097: protected JLabel displayListLabel = new JLabel();
098: protected JList displayList = new JList();
099: protected JScrollPane displayListScroll = new JScrollPane(
100: displayList);
101:
102: // protected JLabel descrListLabel = new JLabel();
103: // protected JList descrList = new JList();
104: // protected JScrollPane descrListScroll = new JScrollPane(descrList);
105:
106: protected GridBagLayout gridbag = new GridBagLayout();
107: protected String parentName = null;
108:
109: protected JTextPane noneText = new JTextPane();
110:
111: protected int modelIndex = -1;
112: protected int valueIndex = 0;
113: protected int displayIndex = 0;
114: // protected int descrIndex = 0;
115:
116: protected int valueType = 0;
117:
118: protected boolean initializing = true;
119:
120: protected class ListItem {
121: public String display;
122: public String table;
123: public String column;
124: public int sqlType = 0;
125: public boolean isNone = false;
126:
127: public String toString() {
128: return display;
129: }
130: }
131:
132: // For performance improvement. No need to get all the contexts in the project
133: private DesignContext[] getDesignContexts(DesignBean designBean) {
134: DesignProject designProject = designBean.getDesignContext()
135: .getProject();
136: DesignContext[] contexts;
137: if (designProject instanceof FacesDesignProject) {
138: contexts = ((FacesDesignProject) designProject)
139: .findDesignContexts(new String[] { "request",
140: "session", "application" });
141: } else {
142: contexts = new DesignContext[0];
143: }
144: DesignContext[] designContexts = new DesignContext[contexts.length + 1];
145: designContexts[0] = designBean.getDesignContext();
146: System.arraycopy(contexts, 0, designContexts, 1,
147: contexts.length);
148: return designContexts;
149: }
150:
151: public ColumnDataBindingPanel(ValueBindingPanel vbp,
152: ColumnDataBindingCustomizer customizer, DesignProperty prop) {
153: this .vbp = vbp;
154: this .customizer = customizer;
155: this .prop = prop;
156: try {
157: jbInit();
158: } catch (Exception e) {
159: e.printStackTrace();
160: }
161: if (prop != null) {
162: //DesignContext[] contexts = prop.getDesignBean().getDesignContext().getProject().getDesignContexts();
163: DesignContext[] contexts = getDesignContexts(prop
164: .getDesignBean());
165:
166: // // first check to see if the comp is in a UIData bound to a RowSet
167: // DesignBean tableBean = scanForParent(UIData.class, prop.getDesignBean());
168: // if (tableBean != null) {
169: // //!JOE do this later...
170: // }
171:
172: // find the current value
173: String currentRef = prop.getValueSource();
174: newRef = currentRef;
175: String contextName = null;
176: String modelName = null;
177: String valueField = null;
178: String displayField = null;
179: // String descrField = null;
180: if (currentRef != null && currentRef.startsWith("#{") && //NOI18N
181: currentRef.endsWith("}")) { //NOI18N
182:
183: List parts = new ArrayList();
184: /*
185: StringTokenizer st = new StringTokenizer(currentRef.substring(2,
186: currentRef.length() - 1), ".");
187: while (st.hasMoreElements()) {
188: parts.add(st.nextElement());
189: }
190: */
191:
192: //MBOHM fix 5086833
193: //there could be internal dots within, say, the selectItems['travel.person.personid,travel.person.name']
194: String strippedRef = currentRef.substring(2, currentRef
195: .length() - 1);
196: int bracesOpen = 0, currStart = 0;
197: String part;
198: for (int i = 0; i < strippedRef.length(); i++) {
199: char c = strippedRef.charAt(i);
200: if (c == '[') {
201: bracesOpen++;
202: } else if (c == ']') {
203: bracesOpen--;
204: } else if (c == '.' && bracesOpen < 1) {
205: part = strippedRef.substring(currStart, i);
206: if (part.length() > 0) {
207: parts.add(part);
208: }
209: currStart = i + 1;
210: }
211: }
212: //get the remaining stuff after the last period
213: if (currStart < strippedRef.length()) {
214: part = strippedRef.substring(currStart);
215: parts.add(part);
216: }
217:
218: if (parts.size() > 0) {
219: contextName = "" + parts.get(0);
220: }
221: if (parts.size() > 1) {
222: modelName = "" + parts.get(1);
223: }
224: if (parts.size() > 2
225: && ((String) parts.get(2))
226: .startsWith("selectItems['")) { //NOI18N
227: String siText = "" + parts.get(2);
228: String fieldList = siText.substring(siText
229: .indexOf("selectItems['")
230: + "selectItems['".length()); //NOI18N
231: fieldList = fieldList.substring(0, fieldList
232: .indexOf("']")); //NOI18N
233:
234: ArrayList fields = new ArrayList();
235: /*
236: StringTokenizer st2 = new StringTokenizer(fieldList, ","); //NOI18N
237: while (st2.hasMoreTokens()) {
238: fields.add(st2.nextToken());
239: }
240: */
241:
242: //MBOHM fix 5086833
243: //could have internal commas, in say, selectItems['employee.employeeid, employee.firstname || \' , \' || employee.lastname']
244: boolean quoteOpen = false;
245: currStart = 0;
246: String field;
247: for (int i = 0; i < fieldList.length(); i++) {
248: char c = fieldList.charAt(i);
249: if (c == '\'') {
250: quoteOpen = !quoteOpen;
251: } else if (c == ',' && !quoteOpen) {
252: field = fieldList.substring(currStart, i);
253: if (field.length() > 0) {
254: fields.add(field);
255: }
256: currStart = i + 1;
257: }
258: }
259: //get the remaining stuff after the last period
260: if (currStart < fieldList.length()) {
261: field = fieldList.substring(currStart);
262: fields.add(field);
263: }
264:
265: valueField = fields.size() > 0 ? "" + fields.get(0)
266: : null; //NOI18N
267: displayField = fields.size() > 1 ? ""
268: + fields.get(1) : null; //NOI18N
269: // descrField = fields.size() > 2 ? "" + fields.get(2) : null;
270: }
271: }
272:
273: // then scan for all rowsets
274: ArrayList rowsetBeans = new ArrayList();
275: for (int i = 0; i < contexts.length; i++) {
276: String scope = (String) contexts[i]
277: .getContextData(Constants.ContextData.SCOPE);
278: if ("request".equals(scope)
279: && contexts[i] != prop.getDesignBean()
280: .getDesignContext()) { //NOI18N
281: continue;
282: }
283: DesignBean[] rsbs = contexts[i]
284: .getBeansOfType(RowSet.class);
285: for (int j = 0; j < rsbs.length; j++) {
286: rowsetBeans.add(rsbs[j]);
287: }
288: }
289:
290: if (rowsetBeans.size() > 0) {
291: for (int i = 0; i < rowsetBeans.size(); i++) {
292: DesignBean rsb = (DesignBean) rowsetBeans.get(i);
293: try {
294: if (modelIndex < 0) {
295: DesignContext rsc = rsb.getDesignContext();
296: if (rsc instanceof FacesDesignContext) {
297: if (((FacesDesignContext) rsc)
298: .getReferenceName().equals(
299: contextName)
300: && rsb.getInstanceName()
301: .equals(modelName)) {
302: modelIndex = i;
303: }
304: } else {
305: if (rsc.getDisplayName().equals(
306: contextName)
307: && rsb.getInstanceName()
308: .equals(modelName)) {
309: modelIndex = i;
310: }
311: }
312: }
313: RowSet rs = (RowSet) rsb.getInstance();
314: if (rs != null) {
315: ResultSetMetaData rsmd = rs.getMetaData();
316:
317: DefaultListModel val_dlm = new DefaultListModel();
318: ListItem val_none = new ListItem();
319: val_none.display = bundle
320: .getMessage("noneBrackets"); //NOI18N
321: val_none.isNone = true;
322: val_dlm.addElement(val_none);
323:
324: DefaultListModel disp_dlm = new DefaultListModel();
325: ListItem disp_none = new ListItem();
326: disp_none.display = bundle
327: .getMessage("useValueBrackets"); //NOI18N
328: disp_dlm.addElement(disp_none);
329:
330: rsCombo.addItem(rsb);
331: valListModelHash.put(rsb, val_dlm);
332: dispListModelHash.put(rsb, disp_dlm);
333:
334: int cols = rsmd.getColumnCount();
335: for (int c = 1; c <= cols; c++) {
336: ListItem li = new ListItem();
337: li.table = rsmd.getTableName(c);
338: li.column = rsmd.getColumnName(c);
339: li.sqlType = rsmd.getColumnType(c);
340: li.display = (li.table == null || li.table
341: .length() == 0) ? li.column
342: : li.table + "." + li.column; //NOI18N
343: val_dlm.addElement(li);
344: disp_dlm.addElement(li);
345: if (modelIndex > -1) {
346: //MBOHM fix 5086833
347: String liColumnEscapeApos = li.column
348: .replaceAll("\\'", "\\\\'"); //NOI18N
349: if (valueIndex <= 0
350: && liColumnEscapeApos
351: .equals(valueField)) {
352: valueIndex = c;
353: }
354: if (displayIndex <= 0
355: && liColumnEscapeApos
356: .equals(displayField)) {
357: displayIndex = c;
358: }
359: // if (descrIndex <= 0 && liColumnEscapeApos.equals(descrField)) {
360: // descrIndex = c;
361: // }
362: }
363: }
364: }
365: } catch (Exception x) {
366: x.printStackTrace();
367: }
368: }
369: } else {
370: this .removeAll();
371: this .add(rsLabel, new GridBagConstraints(0, 0, 1, 1,
372: 0.0, 0.0, GridBagConstraints.WEST,
373: GridBagConstraints.NONE,
374: new Insets(8, 8, 2, 8), 0, 0));
375: this .add(noneText, new GridBagConstraints(0, 1, 1, 1,
376: 1.0, 1.0, GridBagConstraints.CENTER,
377: GridBagConstraints.BOTH,
378: new Insets(0, 8, 8, 8), 0, 0));
379: }
380: }
381: updateLists();
382: if (modelIndex > -1) {
383: rsCombo.setSelectedIndex(modelIndex);
384: }
385: if (valueIndex > -1) {
386: //MBOHM fix 5073036
387: ListModel lm = valueList.getModel();
388: //if <none> is selected and the list has more than one element in it, select the second one
389: if (valueIndex == 0 && lm != null && lm.getSize() > 1) {
390: valueIndex = 1;
391: }
392: valueList.setSelectedIndex(valueIndex);
393: }
394: if (displayIndex > -1) {
395: displayList.setSelectedIndex(displayIndex);
396: }
397: // if (descrIndex > -1) {
398: // descrList.setSelectedIndex(descrIndex);
399: // }
400: initializing = false;
401: updateSelection();
402: repaint(100);
403: }
404:
405: private void jbInit() throws Exception {
406:
407: valueList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
408: displayList
409: .setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
410: noneText.setEditable(false);
411: noneText.setFont(rsLabel.getFont());
412: noneText.setBorder(UIManager.getBorder("TextField.border")); //NOI18N
413: noneText.setText(bundle.getMessage("noRss")); //NOI18N
414:
415: rsLabel.setText(bundle.getMessage("chooseFieldsForItems")); //NOI18N
416:
417: valueListLabel.setText(bundle.getMessage("valField")); //NOI18N
418: displayListLabel.setText(bundle.getMessage("displayField")); //NOI18N
419: // descrListLabel.setText("Description field:");
420: valueListScroll.setPreferredSize(new Dimension(200, 200));
421:
422: rsCombo.setRenderer(new RSComboRenderer());
423:
424: this .setPreferredSize(new Dimension(400, 200));
425: this .setLayout(gridbag);
426:
427: this .add(rsLabel, new GridBagConstraints(0, 0, 2, 1, 0.0, 0.0,
428: GridBagConstraints.WEST, GridBagConstraints.NONE,
429: new Insets(8, 8, 2, 8), 0, 0));
430: this .add(rsCombo, new GridBagConstraints(0, 1, 2, 1, 1.0, 0.0,
431: GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
432: new Insets(0, 8, 8, 8), 0, 0));
433:
434: this .add(valueListLabel, new GridBagConstraints(0, 2, 1, 1,
435: 0.0, 0.0, GridBagConstraints.WEST,
436: GridBagConstraints.NONE, new Insets(0, 8, 2, 8), 0, 0));
437: this .add(valueListScroll, new GridBagConstraints(0, 3, 1, 1,
438: 1.0, 1.0, GridBagConstraints.CENTER,
439: GridBagConstraints.BOTH, new Insets(0, 8, 8, 8), 0, 0));
440:
441: this .add(displayListLabel, new GridBagConstraints(1, 2, 1, 1,
442: 0.0, 0.0, GridBagConstraints.WEST,
443: GridBagConstraints.NONE, new Insets(0, 0, 2, 8), 0, 0));
444: this .add(displayListScroll, new GridBagConstraints(1, 3, 1, 1,
445: 1.0, 1.0, GridBagConstraints.CENTER,
446: GridBagConstraints.BOTH, new Insets(0, 0, 8, 8), 0, 0));
447:
448: // this.add(descrListLabel, new GridBagConstraints(2, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST,
449: // GridBagConstraints.NONE, new Insets(0, 0, 2, 8), 0, 0));
450: // this.add(descrListScroll, new GridBagConstraints(2, 3, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER,
451: // GridBagConstraints.BOTH, new Insets(0, 0, 8, 8), 0, 0));
452:
453: rsCombo.addItemListener(new ItemListener() {
454: public void itemStateChanged(ItemEvent e) {
455: updateLists();
456: }
457: });
458: valueList.addListSelectionListener(new ListSelectionListener() {
459: public void valueChanged(ListSelectionEvent e) {
460: updateSelection();
461: }
462: });
463: displayList
464: .addListSelectionListener(new ListSelectionListener() {
465: public void valueChanged(ListSelectionEvent e) {
466: updateSelection();
467: }
468: });
469: // descrList.addListSelectionListener(new ListSelectionListener() {
470: // public void valueChanged(ListSelectionEvent e) {
471: // updateSelection();
472: // }
473: // });
474: }
475:
476: protected void updateLists() {
477: updateSelection();
478: Object o = valListModelHash.get(rsCombo.getSelectedItem());
479: if (o instanceof ListModel) {
480: ListModel lm = (ListModel) o;
481: valueList.setModel(lm);
482: }
483: o = dispListModelHash.get(rsCombo.getSelectedItem());
484: if (o instanceof ListModel) {
485: ListModel lm = (ListModel) o;
486: displayList.setModel(lm);
487: }
488: updateSelection();
489: }
490:
491: protected void updateSelection() {
492: if (initializing) {
493: return;
494: }
495:
496: DesignBean rsBean = null;
497: String valName = null;
498: String dispName = null;
499: String descName = null;
500:
501: Object o = rsCombo.getSelectedItem();
502: if (o instanceof DesignBean) {
503: rsBean = (DesignBean) o;
504: }
505: o = valueList.getSelectedValue();
506: if (o instanceof ListItem) {
507: valName = ((ListItem) o).column;
508: this .valueType = ((ListItem) o).sqlType;
509: } else {
510: this .valueType = 0;
511: }
512: if (valName != null) { //MBOHM: use this to prevent a selection on display field list when value field list selection is null
513: o = displayList.getSelectedValue();
514: if (o instanceof ListItem) {
515: dispName = ((ListItem) o).column;
516: }
517: if (displayList.isSelectionEmpty()) {
518: displayList.setSelectedIndex(0);
519: }
520: } else {
521: displayList.clearSelection();
522: }//MBOHM
523: // o = descrList.getSelectedValue();
524: // if (o instanceof ListItem) {
525: // descName = ((ListItem)o).column;
526: // }
527:
528: displayListLabel.setEnabled(valName != null);
529: displayList.setEnabled(valName != null);
530:
531: String ref = calcValueRef(rsBean, valName, dispName); //, descName);
532:
533: if (vbp != null) {
534: vbp.setSelectItemsValueType(valueType);
535: vbp.setValueBinding(ref);
536: } else if (customizer != null) {
537: newRef = ref;
538: customizer.firePropertyChange();
539: } else {
540: prop.setValueSource(ref);
541: }
542: }
543:
544: public boolean isModified() {
545: String curRef = prop.getValueSource();
546: return !((curRef == null && newRef == null) || (curRef != null && curRef
547: .equals(newRef)));
548: }
549:
550: String newRef = null;
551:
552: public void customizerApply() {
553: // start with the UISelectItems bean
554: //MBOHM for 6194849, no harm in calling this line here
555: newRef = HtmlDesignInfoBase.maybeSetupDefaultSelectItems(prop
556: .getDesignBean(), newRef);
557: prop.setValueSource(newRef);
558: //MBOHM 6194849 //HtmlDesignInfoBase.maybeSetupConverter(prop.getDesignBean(), valueType);
559: //newRef = null;
560: }
561:
562: protected String calcValueRef(DesignBean rsBean,
563: String valueColumn, String labelColumn) { //, String descrColumn) {
564: if (rsBean == null || valueColumn == null
565: || valueColumn.length() == 0) {
566: return null; //NOI18N
567: }
568:
569: String ref = valueColumn
570: + (labelColumn != null ? "," + labelColumn : ""); // + (descrColumn != null ? "_" + descrColumn : ""); //NOI18N
571: //MBOHM fix 5086833
572: ref = ref.replaceAll("\\'", "\\\\'"); //NOI18N
573: DesignContext c = rsBean.getDesignContext();
574: if (c instanceof FacesDesignContext) {
575: return "#{" + ((FacesDesignContext) c).getReferenceName()
576: + "." + rsBean.getInstanceName() + ".selectItems['"
577: + ref + "']}"; //NOI18N
578: } else {
579: return "#{" + c.getDisplayName() + "."
580: + rsBean.getInstanceName() + ".selectItems['" + ref
581: + "']}"; //NOI18N
582: }
583: }
584:
585: class RSComboRenderer extends DefaultListCellRenderer {
586: public Component getListCellRendererComponent(JList list,
587: Object value, int index, boolean isSelected,
588: boolean cellHasFocus) {
589: super .getListCellRendererComponent(list, value, index,
590: isSelected, cellHasFocus);
591: DesignBean rsBean = (DesignBean) value;
592: this .setText(bundle.getMessage("rsDisplayTextPattern",
593: rsBean.getInstanceName(), rsBean.getDesignContext()
594: .getDisplayName())); //NOI18N
595: return this;
596: }
597: }
598: }
|