0001: /*
0002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003: *
0004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * The contents of this file are subject to the terms of either the GNU
0007: * General Public License Version 2 only ("GPL") or the Common
0008: * Development and Distribution License("CDDL") (collectively, the
0009: * "License"). You may not use this file except in compliance with the
0010: * License. You can obtain a copy of the License at
0011: * http://www.netbeans.org/cddl-gplv2.html
0012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013: * specific language governing permissions and limitations under the
0014: * License. When distributing the software, include this License Header
0015: * Notice in each file and include the License file at
0016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
0017: * particular file as subject to the "Classpath" exception as provided
0018: * by Sun in the GPL Version 2 section of the License file that
0019: * accompanied this code. If applicable, add the following below the
0020: * License Header, with the fields enclosed by brackets [] replaced by
0021: * your own identifying information:
0022: * "Portions Copyrighted [year] [name of copyright owner]"
0023: *
0024: * Contributor(s):
0025: *
0026: * The Original Software is NetBeans. The Initial Developer of the Original
0027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
0028: * Microsystems, Inc. All Rights Reserved.
0029: *
0030: * If you wish your version of this file to be governed by only the CDDL
0031: * or only the GPL Version 2, indicate your decision by adding
0032: * "[Contributor] elects to include this software in this distribution
0033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034: * single choice of license, a recipient has the option to distribute
0035: * your version of this file under either the CDDL, the GPL Version 2 or
0036: * to extend the choice of license to its licensees as provided above.
0037: * However, if you add GPL Version 2 code and therefore, elected the GPL
0038: * Version 2 license, then the option applies only if the new code is
0039: * made subject to such option by the copyright holder.
0040: */
0041: package org.netbeans.modules.visualweb.faces.dt;
0042:
0043: import com.sun.data.provider.DataProvider;
0044: import com.sun.data.provider.FieldKey;
0045: import com.sun.rave.designtime.faces.FacesDesignProperty;
0046: import java.beans.BeanDescriptor;
0047: import java.beans.BeanInfo;
0048: import java.beans.IntrospectionException;
0049: import java.beans.Introspector;
0050: import java.beans.PropertyDescriptor;
0051: import java.sql.Connection;
0052: import java.sql.DatabaseMetaData;
0053: import java.sql.DriverManager;
0054: import java.sql.ResultSet;
0055: import java.sql.ResultSetMetaData;
0056: import java.sql.SQLException;
0057: import java.sql.Types;
0058: import java.util.ArrayList;
0059: import java.util.HashMap;
0060: import javax.faces.application.Application;
0061: import javax.faces.component.UIComponent;
0062: import javax.faces.component.UIInput;
0063: import javax.faces.component.UISelectItems;
0064: import javax.faces.component.UISelectMany;
0065: import javax.faces.component.UISelectOne;
0066: import javax.faces.context.FacesContext;
0067: import javax.faces.convert.Converter;
0068: import javax.faces.convert.NumberConverter;
0069: import javax.faces.el.MethodBinding;
0070: import javax.faces.validator.Validator;
0071: import javax.naming.Context;
0072: import javax.naming.InitialContext;
0073: import javax.naming.NamingException;
0074: import javax.sql.DataSource;
0075: import javax.sql.RowSet;
0076: import com.sun.rave.designtime.DisplayAction;
0077: import com.sun.rave.designtime.DesignBean;
0078: import com.sun.rave.designtime.DesignInfo;
0079: import com.sun.rave.designtime.DesignContext;
0080: import com.sun.rave.designtime.CustomizerResult;
0081: import com.sun.rave.designtime.DesignEvent;
0082: import com.sun.rave.designtime.DesignProperty;
0083: import com.sun.rave.designtime.Result;
0084: import com.sun.rave.designtime.faces.FacesDesignContext;
0085: import java.util.List;
0086: import javax.faces.component.NamingContainer;
0087: import javax.faces.component.html.HtmlCommandLink;
0088:
0089: import com.sun.data.provider.impl.CachedRowSetDataProvider;
0090: import com.sun.rave.designtime.DesignProject;
0091: import com.sun.rave.designtime.faces.FacesDesignProject;
0092: import com.sun.rave.faces.data.DefaultSelectItemsArray;
0093: import com.sun.rave.faces.data.RowSetDataModel;
0094: import org.netbeans.modules.visualweb.faces.dt.component.html.HtmlFormDesignInfo;
0095: import org.netbeans.modules.visualweb.faces.dt.util.ComponentBundle;
0096: import org.netbeans.modules.visualweb.faces.dt.converter.NumberConverterCustomizer;
0097: import javax.faces.el.ValueBinding;
0098: import org.netbeans.modules.visualweb.propertyeditors.binding.data.DataBindingHelper;
0099:
0100: public abstract class HtmlDesignInfoBase implements DesignInfo {
0101:
0102: private static final ComponentBundle bundle = ComponentBundle
0103: .getBundle(HtmlDesignInfoBase.class);
0104: protected static final String BEAN_DESCRIPTOR_PROPERTY_DESCRIPTOR_MAP_CACHE_KEY = HtmlDesignInfoBase.class
0105: .getName()
0106: + "-PropertyDescriptorMapCache"; // NOI18N
0107:
0108: public boolean acceptParent(DesignBean parentBean,
0109: DesignBean childBean, Class childClass) {
0110: return true;
0111: }
0112:
0113: public boolean acceptChild(DesignBean parentBean,
0114: DesignBean childBean, Class childClass) {
0115: return true;
0116: }
0117:
0118: public Result beanCreatedSetup(DesignBean bean) {
0119: return Result.SUCCESS;
0120: }
0121:
0122: public Result beanPastedSetup(DesignBean bean) {
0123: return Result.SUCCESS;
0124: }
0125:
0126: public Result beanDeletedCleanup(DesignBean bean) {
0127: modifyVirtualFormsOnBeanDeletedCleanup(bean);
0128: return Result.SUCCESS;
0129: }
0130:
0131: /** Find the containing form, if it exists. */
0132: /*
0133: * Be sure to keep this method in sync with the version in
0134: * <code>com.sun.rave.web.ui.design.AbstractDesignInfo</code> (in webui).</p>
0135: */
0136: private DesignBean findFormBean(DesignBean bean) {
0137: DesignBean formBean = null;
0138: DesignBean testBean = null;
0139: if (bean != null) {
0140: testBean = bean.getBeanParent();
0141: }
0142: while (testBean != null) {
0143: Object testInstance = testBean.getInstance();
0144: if (testInstance != null
0145: && "com.sun.rave.web.ui.component.Form"
0146: .equals(testInstance.getClass().getName())) {
0147: formBean = testBean;
0148: break;
0149: }
0150: testBean = testBean.getBeanParent();
0151: }
0152: return formBean;
0153: }
0154:
0155: /*
0156: * Be sure to keep this method in sync with the version in
0157: * <code>com.sun.rave.web.ui.design.AbstractDesignInfo</code> (in webui).</p>
0158: */
0159: protected void modifyVirtualFormsOnBeanDeletedCleanup(
0160: DesignBean bean) {
0161: //find the containing form, if it exists
0162: DesignBean formBean = findFormBean(bean);
0163: //make sure the id for the bean being deleted is removed from the virtualFormsConfig property
0164: if (formBean != null) {
0165: DesignProperty vformsConfigProp = formBean
0166: .getProperty("virtualFormsConfig"); //NOI18N
0167: if (vformsConfigProp != null) {
0168: Object vformsConfigValueObj = vformsConfigProp
0169: .getValue();
0170: if (vformsConfigValueObj instanceof String) {
0171: String vfc = (String) vformsConfigValueObj;
0172: HtmlFormDesignInfo.VirtualFormDescriptor[] descriptors = HtmlFormDesignInfo
0173: .generateVirtualForms(vfc);
0174: String beanId = HtmlFormDesignInfo
0175: .getFullyQualifiedId(bean);
0176: boolean modified = false;
0177: if (beanId != null) {
0178: modified = removeIdFromVirtualFormDescriptors(
0179: descriptors, beanId); //potentially modifies descriptors object
0180: }
0181: if (modified) {
0182: String newVfc = HtmlFormDesignInfo
0183: .generateVirtualFormsConfig(descriptors);
0184: vformsConfigProp.setValue(newVfc);
0185: }
0186: }
0187: }
0188: }
0189: }
0190:
0191: /*
0192: * Be sure to keep this method in sync with the version in
0193: * <code>com.sun.rave.web.ui.design.AbstractDesignInfo</code> (in webui).</p>
0194: */
0195: private boolean removeIdFromVirtualFormDescriptors(
0196: HtmlFormDesignInfo.VirtualFormDescriptor[] descriptors,
0197: String idToRemove) {
0198: boolean modified = false;
0199: for (int d = 0; descriptors != null && d < descriptors.length; d++) {
0200: HtmlFormDesignInfo.VirtualFormDescriptor vfd = descriptors[d];
0201:
0202: String[] pids = vfd.getParticipatingIds();
0203: String[] newPids = removeIdFromArray(pids, idToRemove);
0204: if (pids != null && newPids != null
0205: && pids.length != newPids.length) {
0206: modified = true;
0207: }
0208: vfd.setParticipatingIds(newPids);
0209:
0210: String[] sids = vfd.getSubmittingIds();
0211: String[] newSids = removeIdFromArray(sids, idToRemove);
0212: if (sids != null && newSids != null
0213: && sids.length != newSids.length) {
0214: modified = true;
0215: }
0216: vfd.setSubmittingIds(newSids);
0217: }
0218: return modified;
0219: }
0220:
0221: /*
0222: * Be sure to keep this method in sync with the version in
0223: * <code>com.sun.rave.web.ui.design.AbstractDesignInfo</code> (in webui).</p>
0224: */
0225: private String[] removeIdFromArray(String[] ids, String idToRemove) {
0226: if (ids == null || ids.length == 0) {
0227: return ids;
0228: }
0229: List list = new ArrayList();
0230: for (int i = 0; i < ids.length; i++) {
0231: String id = ids[i]; //might be namespaced
0232: if (id != null
0233: && id.length() > 0
0234: && !HtmlFormDesignInfo
0235: .fullyQualifiedIdMatchesPattern(idToRemove,
0236: id)) { //id in array does not represent fqId being removed
0237: list.add(id);
0238: }
0239: }
0240: return (String[]) list.toArray(new String[list.size()]);
0241: }
0242:
0243: /**
0244: * Return the BeanInfo class of my getBeanClass().
0245: * May return nil if an error is encountered on retrieving BeanInfo.
0246: *
0247: * @return
0248: * @throws IntrospectionException
0249: */
0250: protected BeanInfo getBeanInfo() throws IntrospectionException {
0251:
0252: return Introspector.getBeanInfo(getBeanClass());
0253: }
0254:
0255: protected BeanDescriptor getBeanDescriptor() {
0256:
0257: try {
0258: BeanInfo beanInfo = getBeanInfo();
0259: return beanInfo.getBeanDescriptor();
0260: } catch (IntrospectionException e) {
0261: return null;
0262: }
0263: }
0264:
0265: protected PropertyDescriptor getPropertyDescriptorNamed(
0266: String propertyName) {
0267:
0268: if (propertyName == null) {
0269: return null;
0270: }
0271: BeanInfo beanInfo;
0272: try {
0273: beanInfo = getBeanInfo();
0274: } catch (IntrospectionException e) {
0275: beanInfo = null;
0276: }
0277: if (beanInfo == null) {
0278: return null;
0279: }
0280: BeanDescriptor beanDescriptor = beanInfo.getBeanDescriptor();
0281: // if I have no way of caching a hashmap then do it iteratively
0282: if (beanDescriptor == null) {
0283: PropertyDescriptor propertyDescriptors[] = beanInfo
0284: .getPropertyDescriptors();
0285: if (propertyDescriptors == null) {
0286: return null;
0287: }
0288: for (int i = 0, max = propertyDescriptors.length; i < max; i++) {
0289: PropertyDescriptor propertyDescriptor = propertyDescriptors[i];
0290: if (propertyName.equals(propertyDescriptor.getName())) {
0291: return propertyDescriptor;
0292: }
0293: }
0294: return null;
0295: }
0296: // since BeanDescriptors allow me to store named values, I can create a hash map and use it to do the lookup
0297: // instead of doing it iterativelly
0298: HashMap propertyDescriptorsByName = (HashMap) beanDescriptor
0299: .getValue(BEAN_DESCRIPTOR_PROPERTY_DESCRIPTOR_MAP_CACHE_KEY);
0300: if (propertyDescriptorsByName != null) {
0301: return (PropertyDescriptor) propertyDescriptorsByName
0302: .get(propertyName);
0303: }
0304: PropertyDescriptor propertyDescriptors[] = beanInfo
0305: .getPropertyDescriptors();
0306: propertyDescriptorsByName = new HashMap(
0307: propertyDescriptors.length);
0308: for (int i = 0, max = propertyDescriptors.length; i < max; i++) {
0309: PropertyDescriptor propertyDescriptor = propertyDescriptors[i];
0310: propertyDescriptorsByName.put(propertyDescriptor.getName(),
0311: propertyDescriptor);
0312: }
0313: beanDescriptor.setValue(
0314: BEAN_DESCRIPTOR_PROPERTY_DESCRIPTOR_MAP_CACHE_KEY,
0315: propertyDescriptorsByName);
0316: return (PropertyDescriptor) propertyDescriptorsByName
0317: .get(propertyName);
0318: }
0319:
0320: /**
0321: * Returns the list (or hierarchy) of items to be included in a right-click context menu for
0322: * this bean at design-time.
0323: *
0324: * @param bean The DesignBean that a user has right-clicked on
0325: * @return An array of DisplayAction objects representing a context menu to display to the user
0326: */
0327: public DisplayAction[] getContextItems(DesignBean bean) {
0328: // Use the new data binding dialogs that support Data providers
0329: ArrayList actions = new ArrayList();
0330: DesignProperty property = bean.getProperty("value");
0331: if (property != null) {
0332: Class bindingPanelClass = DataBindingHelper.BIND_VALUE_TO_DATAPROVIDER;
0333: DisplayAction bindToDataAction = DataBindingHelper
0334: .getDataBindingAction(
0335: bean,
0336: property.getPropertyDescriptor().getName(),
0337: new Class[] {
0338: bindingPanelClass,
0339: DataBindingHelper.BIND_VALUE_TO_OBJECT });
0340:
0341: if (!(bean.getInstance() instanceof HtmlCommandLink)) {
0342: actions.add(bindToDataAction);
0343: }
0344: if (bean.getInstance() instanceof UIInput) {
0345: actions.add(new AutoSubmitOnChangeCheckedAction(bean));
0346: }
0347: }
0348: return (DisplayAction[]) actions
0349: .toArray(new DisplayAction[actions.size()]);
0350: }
0351:
0352: /**
0353: * This method is called when an object from a design surface or palette is being dragged 'over'
0354: * a JavaBean type handled by this DesignInfo. If the 'sourceClass' is of interest to the
0355: * 'targetBean' instance (they can be "linked"), this method should return <b>true</b>. The
0356: * user will then be presented with visual cues that this is an appropriate place to 'drop' the
0357: * item and establish a link. If the user decides to drop the item on this targetBean, the
0358: * 'linkBeans' method will be called.
0359: *
0360: * @param targetBean The DesignBean instance that the user is 'hovering' the mouse over
0361: * @param sourceBean The DesignBean instance that the user may potentially 'drop' to link (may be null)
0362: * @param sourceClass The class type of the object that the user may potentially 'drop' to link
0363: * @return <b>true</b> if the 'targetBean' cares to have an instance of type 'sourceClass'
0364: * linked to it, <b>false</b> if not
0365: * @see linkBeans
0366: */
0367: public boolean acceptLink(DesignBean targetBean,
0368: DesignBean sourceBean, Class sourceClass) {
0369:
0370: boolean retVal = false;
0371: if (canLinkConverterOrValidatorBeans(targetBean, sourceClass)) {
0372: retVal = true;
0373: }
0374: if (!retVal) {
0375: boolean isDatabaseClass = isResultSetClass(sourceClass);
0376: DesignProperty valueProp = targetBean.getProperty("value"); // NOI18N
0377: retVal = isDatabaseClass && valueProp != null;
0378: }
0379: if (!retVal) {
0380: if (DataProvider.class.isAssignableFrom(sourceClass)) {
0381: DesignProperty valueProp = targetBean
0382: .getProperty("value"); // NOI18N
0383: retVal = valueProp != null;
0384: }
0385: }
0386: return retVal;
0387: }
0388:
0389: /**
0390: * <P>This method is called when an object from a design surface or palette has been dropped
0391: * 'on' a JavaBean type handled by this DesignInfo (to establish a link). This method will
0392: * not be called unless the corresponding 'acceptLink' method call returned <b>true</b>.
0393: * Typically, this results in property settings on potentially both of the DesignBean objects.</P>
0394: *
0395: * @param targetBean The target DesignBean instance that the user has 'dropped' an object onto to
0396: * establish a link
0397: * @param sourceBean The DesignBean instance that has been 'dropped'
0398: * @return A Result object, indicating success or failure and including messages for the user
0399: * @see acceptLink
0400: */
0401: public Result linkBeans(DesignBean targetBean, DesignBean sourceBean) {
0402:
0403: // if cachedRowSetDataProvider, switch the sourceBean to
0404: // it's rowset.
0405: if (isCachedRowSetDP(sourceBean.getInstance())) {
0406: DesignBean db = findCachedRowSetBean(sourceBean);
0407: if (db != null) {
0408: sourceBean = db;
0409: }
0410: }
0411: if (sourceBean.getInstance() instanceof RowSetDataModel) {
0412: try {
0413: RowSetDataModel rsdm = (RowSetDataModel) sourceBean
0414: .getInstance();
0415: ResultSet rs = (ResultSet) rsdm.getWrappedData();
0416: if (rs != null) {
0417: ResultSetMetaData rsmd = rs.getMetaData();
0418: if (rsmd.getColumnCount() >= 1) {
0419: String table = rsmd.getTableName(1);
0420: String column = rsmd.getColumnName(1);
0421: DesignBean rootBean = sourceBean
0422: .getDesignContext().getRootContainer();
0423: String outerName = rootBean.getInstanceName();
0424: String valueRef = "#{" + outerName + "."
0425: + sourceBean.getInstanceName()
0426: + ".rowData." + column + "}"; //NOI18N
0427: targetBean.getProperty("value").setValueSource(
0428: valueRef); //NOI18N
0429: }
0430: }
0431: } catch (Exception x) {
0432: x.printStackTrace();
0433: }
0434: } else if (sourceBean.getInstance() instanceof ResultSet) {
0435: try {
0436: ResultSet rs = (ResultSet) sourceBean.getInstance();
0437: ResultSetMetaData rsmd = rs.getMetaData();
0438: if (rsmd.getColumnCount() >= 1) {
0439: String table = rsmd.getTableName(1);
0440: String column = rsmd.getColumnName(1);
0441: DesignBean rootBean = sourceBean.getDesignContext()
0442: .getRootContainer();
0443: String outerName = rootBean.getInstanceName();
0444: String valueRef = "#{" + outerName + "."
0445: + sourceBean.getInstanceName()
0446: + ".currentRow['" + column + "']}"; //NOI18N
0447: targetBean.getProperty("value").setValueSource(
0448: valueRef); //NOI18N
0449: // String dtvalue = "[" + table + "." + column + "]";
0450: // targetBean.getDesignContext().setContextData(targetBean.getInstanceName() + ".databind", dtvalue);
0451: }
0452: } catch (Exception x) {
0453: x.printStackTrace();
0454: }
0455: }
0456: ;
0457:
0458: try {
0459: if (canLinkConverterOrValidatorBeans(targetBean, sourceBean)) {
0460: linkConverterOrValidatorBeans(targetBean, sourceBean);
0461: return Result.SUCCESS;
0462: }
0463: } catch (Exception e) {
0464: e.printStackTrace();
0465: return Result.FAILURE;
0466: }
0467: return Result.SUCCESS;
0468: }
0469:
0470: public void beanContextActivated(DesignBean bean) {
0471: }
0472:
0473: public void beanContextDeactivated(DesignBean bean) {
0474: }
0475:
0476: public void instanceNameChanged(DesignBean bean,
0477: String oldInstanceName) {
0478: }
0479:
0480: public void beanChanged(DesignBean bean) {
0481: }
0482:
0483: public void propertyChanged(DesignProperty prop, Object oldValue) {
0484: modifyVirtualFormsOnPropertyChanged(prop, oldValue);
0485: modifyAutoSubmitOnPropertyChanged(prop);
0486: }
0487:
0488: /*
0489: * Be sure to keep this method in sync with the version in
0490: * <code>com.sun.rave.web.ui.design.AbstractDesignInfo</code> (in webui).</p>
0491: */
0492: private void modifyAutoSubmitOnPropertyChanged(
0493: DesignProperty property) {
0494: PropertyDescriptor pd = property.getPropertyDescriptor();
0495: String propertyName = pd.getName();
0496: if ("id".equals(propertyName)) { //NOI18N
0497: DesignBean bean = property.getDesignBean();
0498: //technically, should probably be checking for EditableValueHolder rather than UIInput, but
0499: //getContextItems checks for UIInput, and this must match
0500: if (bean != null && bean.getInstance() instanceof UIInput) {
0501: AutoSubmitOnChangeCheckedAction autoSubmitAction = new AutoSubmitOnChangeCheckedAction(
0502: bean);
0503: if (autoSubmitAction.isAutoSubmit()) {
0504: //toggle twice
0505: autoSubmitAction.toggleAutoSubmit();
0506: autoSubmitAction.toggleAutoSubmit();
0507: }
0508: }
0509: }
0510: }
0511:
0512: /*
0513: * Be sure to keep this method in sync with the version in
0514: * <code>com.sun.rave.web.ui.design.AbstractDesignInfo</code> (in webui).</p>
0515: */
0516: private void modifyVirtualFormsOnPropertyChanged(
0517: DesignProperty property, Object oldValue) {
0518: PropertyDescriptor pd = property.getPropertyDescriptor();
0519: String propertyName = pd.getName();
0520: if ("id".equals(propertyName) && oldValue instanceof String) { //NOI18N
0521: //get virtual form descriptors
0522: DesignBean bean = property.getDesignBean();
0523: if (bean != null) {
0524: String fqId = HtmlFormDesignInfo
0525: .getFullyQualifiedId(bean);
0526: String replacementId = fqId;
0527: if (replacementId == null) {
0528: //try using just straight id
0529: Object replacementIdObj = property.getValue();
0530: if (replacementIdObj instanceof String) {
0531: replacementId = (String) replacementIdObj;
0532: }
0533: } else if (replacementId.startsWith(String
0534: .valueOf(NamingContainer.SEPARATOR_CHAR))
0535: && replacementId.length() > 1) {
0536: //fully qualified replacementId (starting with ":") could look intimidating to users. so just chop off leading ":"
0537: replacementId = replacementId.substring(1,
0538: replacementId.length());
0539: }
0540: if (replacementId != null) {
0541: DesignBean formBean = findFormBean(bean);
0542: if (formBean != null) {
0543: DesignProperty vfcProp = formBean
0544: .getProperty("virtualFormsConfig"); //NOI18N
0545: if (vfcProp != null) {
0546: Object vfcObj = vfcProp.getValue();
0547: if (vfcObj instanceof String) {
0548: String vfc = (String) vfcObj;
0549: HtmlFormDesignInfo.VirtualFormDescriptor[] vfds = HtmlFormDesignInfo
0550: .generateVirtualForms(vfc);
0551: if (vfds != null && vfds.length > 0) {
0552: //get old fully qualified id
0553: DesignBean parentBean = bean
0554: .getBeanParent();
0555: if (parentBean != null) {
0556: String parentBeanFqId = HtmlFormDesignInfo
0557: .getFullyQualifiedId(parentBean);
0558: if (parentBeanFqId != null
0559: && parentBeanFqId
0560: .length() > 0) {
0561: String oldFqId = parentBeanFqId;
0562: String sep = String
0563: .valueOf(NamingContainer.SEPARATOR_CHAR);
0564: if (!sep.equals(oldFqId))
0565: oldFqId += sep;
0566: oldFqId += oldValue;
0567: boolean vfdsModified = false;
0568: for (int v = 0; v < vfds.length; v++) {
0569: String[] participants = vfds[v]
0570: .getParticipatingIds();
0571: String[] submitters = vfds[v]
0572: .getSubmittingIds();
0573: boolean pMod = modifyIdArray(
0574: participants,
0575: oldFqId,
0576: replacementId);
0577: boolean sMod = modifyIdArray(
0578: submitters,
0579: oldFqId,
0580: replacementId);
0581: if (pMod || sMod)
0582: vfdsModified = true;
0583: }
0584: if (vfdsModified) {
0585: String newVfc = HtmlFormDesignInfo
0586: .generateVirtualFormsConfig(vfds);
0587: vfcProp
0588: .setValue(newVfc);
0589: }
0590: }
0591: }
0592: }
0593: }
0594: }
0595: }
0596: }
0597: }
0598: }
0599: }
0600:
0601: /*
0602: * Be sure to keep this method in sync with the version in
0603: * <code>com.sun.rave.web.ui.design.AbstractDesignInfo</code> (in webui).</p>
0604: */
0605: private boolean modifyIdArray(String[] ids, String oldFqId,
0606: String replacementId) {
0607: if (ids == null || ids.length < 1)
0608: return false;
0609: boolean modified = false;
0610: ;
0611: for (int i = 0; i < ids.length; i++) {
0612: String id = ids[i]; //could be qualified
0613: boolean idRepresentsOldFqId = HtmlFormDesignInfo
0614: .fullyQualifiedIdMatchesPattern(oldFqId, id);
0615: if (idRepresentsOldFqId) {
0616: ids[i] = replacementId;
0617: modified = true;
0618: }
0619: }
0620: return modified;
0621: }
0622:
0623: public void eventChanged(DesignEvent event) {
0624: }
0625:
0626: public Result linkBeans(DesignBean targetBean,
0627: DesignBean sourceBean, int[] types) {
0628: int[][] _types = new int[1][];
0629: _types[0] = types;
0630: return linkBeans(targetBean, sourceBean, _types);
0631: }
0632:
0633: public Result linkBeans(DesignBean targetBean,
0634: DesignBean sourceBean, int[][] types) {
0635: if (sourceBean.getInstance() instanceof RowSetDataModel) {
0636: try {
0637: RowSetDataModel rsdm = (RowSetDataModel) sourceBean
0638: .getInstance();
0639: ResultSet rs = (ResultSet) rsdm.getWrappedData();
0640: if (rs != null) {
0641: ResultSetMetaData rsmd = rs.getMetaData();
0642: int col = findAppropriateColumn(rsmd, types);
0643: if (col != -1) {
0644: String table = rsmd.getTableName(col);
0645: String column = rsmd.getColumnName(col);
0646: String outerName = sourceBean
0647: .getDesignContext().getRootContainer()
0648: .getInstanceName();
0649: String valueRef = "#{" + outerName + "."
0650: + sourceBean.getInstanceName() //NOI18N
0651: + ".rowData." + column + "}"; //NOI18N
0652: String dtvalue = "[" + table + "." + column
0653: + "]"; //NOI18N
0654: targetBean.getProperty("value").setValue(
0655: valueRef); //NOI18N
0656: targetBean.getDesignContext().setContextData(
0657: targetBean.getInstanceName()
0658: + ".databind", dtvalue); //NOI18N
0659: }
0660: }
0661: } catch (Exception e) {
0662: e.printStackTrace();
0663: return Result.FAILURE;
0664: }
0665: }
0666: return Result.SUCCESS;
0667: }
0668:
0669: /*
0670: * the following method is called by getContextItems for components that contain SelectItems
0671: */
0672: public DisplayAction[] selectOneGetContextItems(DesignBean bean) {
0673:
0674: // Use the new data binding dialogs that support Data providers
0675:
0676: DesignProperty selectionProperty = bean.getProperty("value");
0677: Class selectionBindingPanelClass = DataBindingHelper.BIND_VALUE_TO_DATAPROVIDER;
0678: DisplayAction bindSelectionToDataAction = DataBindingHelper
0679: .getDataBindingAction(
0680: bean,
0681: selectionProperty.getPropertyDescriptor()
0682: .getName(),
0683: new Class[] { selectionBindingPanelClass,
0684: DataBindingHelper.BIND_VALUE_TO_OBJECT },
0685: true,
0686: bundle.getMessage("bindSelectionToDataEllipse"),
0687: bundle.getMessage("bindSelectionToData"));
0688:
0689: DesignBean selectItemsBean = null;
0690:
0691: int childCount = bean.getChildBeanCount();
0692: for (int i = 0; i < childCount; i++) {
0693: selectItemsBean = bean.getChildBean(i);
0694: if (bean.getChildBean(i).getInstance() instanceof UISelectItems) {
0695: break;
0696: }
0697: }
0698: if (selectItemsBean != null) {
0699: DesignProperty property = selectItemsBean
0700: .getProperty("value");
0701: if (property != null) {
0702: Class bindingPanelClass = DataBindingHelper.BIND_OPTIONS_TO_DATAPROVIDER;
0703: DisplayAction bindToDataAction = DataBindingHelper
0704: .getDataBindingAction(
0705: selectItemsBean,
0706: property.getPropertyDescriptor()
0707: .getName(),
0708: new Class[] {
0709: bindingPanelClass,
0710: DataBindingHelper.BIND_VALUE_TO_OBJECT });
0711: return new DisplayAction[] {
0712: new AutoSubmitOnChangeCheckedAction(bean),
0713: bindToDataAction
0714: // See bug 6324729 - as per Jeffs comment removing it
0715: //bindSelectionToDataAction
0716: };
0717: }
0718: }
0719: return new DisplayAction[0];
0720: }
0721:
0722: public DisplayAction[] selectManyGetContextItems(DesignBean bean) {
0723: // Use the new data binding dialogs that support Data providers
0724:
0725: DesignBean selectItemsBean = null;
0726: int childCount = bean.getChildBeanCount();
0727: for (int i = 0; i < childCount; i++) {
0728: selectItemsBean = bean.getChildBean(i);
0729: if (bean.getChildBean(i).getInstance() instanceof UISelectItems) {
0730: break;
0731: }
0732: }
0733: if (selectItemsBean != null) {
0734: DesignProperty property = selectItemsBean
0735: .getProperty("value");
0736: if (property != null) {
0737: Class bindingPanelClass = DataBindingHelper.BIND_OPTIONS_TO_DATAPROVIDER;
0738: DisplayAction bindToDataAction = DataBindingHelper
0739: .getDataBindingAction(
0740: selectItemsBean,
0741: property.getPropertyDescriptor()
0742: .getName(),
0743: new Class[] {
0744: bindingPanelClass,
0745: DataBindingHelper.BIND_VALUE_TO_OBJECT });
0746: return new DisplayAction[] {
0747: new AutoSubmitOnChangeCheckedAction(bean),
0748: bindToDataAction };
0749: }
0750: }
0751: return new DisplayAction[0];
0752: }
0753:
0754: /*
0755: * the following method is called by beanCreated for components that contain SelectItems
0756: */
0757: public Result selectOneBeanCreated(DesignBean bean) {
0758: try {
0759: DesignContext context = bean.getDesignContext();
0760: // create and setup a default items array
0761: DesignBean items = context
0762: .createBean(
0763: DefaultSelectItemsArray.class.getName(),
0764: null, null);
0765: items.setInstanceName(bean.getInstanceName()
0766: + "DefaultItems", true); //NOI18N
0767:
0768: // create a selectitems child
0769: if (context.canCreateBean(UISelectItems.class.getName(),
0770: bean, null)) {
0771: DesignBean si = context.createBean(UISelectItems.class
0772: .getName(), bean, null);
0773: if (si != null) {
0774: si.setInstanceName(bean.getInstanceName()
0775: + "SelectItems", true); //NOI18N
0776: String outer = ((FacesDesignContext) bean
0777: .getDesignContext()).getReferenceName();
0778: si.getProperty("value").setValueSource(
0779: "#{" + outer + "." + //NOI18N
0780: items.getInstanceName() + "}"); //NOI18N
0781: }
0782: }
0783: } catch (Exception e) {
0784: e.printStackTrace();
0785: }
0786: return Result.SUCCESS;
0787: }
0788:
0789: public Result selectManyBeanCreated(DesignBean bean) {
0790: return selectOneBeanCreated(bean);
0791: }
0792:
0793: public Result selectManyBeanPasted(DesignBean bean) {
0794: return selectOneBeanPasted(bean);
0795: }
0796:
0797: /*
0798: * the following method is called by beanCreated for components that contain SelectItems
0799: */
0800: public Result selectOneBeanPasted(DesignBean bean) {
0801: try {
0802: DesignContext context = bean.getDesignContext();
0803: final String itemsName = bean.getInstanceName()
0804: + "DefaultItems"; //NOI18N
0805: final String selectItemsName = bean.getInstanceName()
0806: + "SelectItems"; //NOI18N
0807: // See if the component has selectItems assigned
0808: DesignBean si = context.getBeanByName(selectItemsName);
0809: if (si != null) {
0810: String source = si.getProperty("value")
0811: .getValueSource(); //NOI18N
0812: // If value refers to the defaultItems we would create automatically, then go ahead and create them
0813: if (source != null && source.indexOf(itemsName) >= 0) {
0814: DesignBean items = context.createBean(
0815: DefaultSelectItemsArray.class.getName(),
0816: null, null);
0817: items.setInstanceName(itemsName, true);
0818: }
0819: }
0820: } catch (Exception e) {
0821: e.printStackTrace();
0822: }
0823: return Result.SUCCESS;
0824: }
0825:
0826: public Result selectOneBeanDeleted(DesignBean bean) {
0827: try {
0828: DesignContext context = bean.getDesignContext();
0829: // find and kill the default items array
0830: DesignBean defaultItemsBean = context.getBeanByName(bean
0831: .getInstanceName()
0832: + "DefaultItems"); //NOI18N
0833: if (defaultItemsBean != null
0834: && defaultItemsBean.getInstance() instanceof DefaultSelectItemsArray) {
0835: context.deleteBean(defaultItemsBean);
0836: }
0837: // find and kill the default converter
0838: DesignBean converterBean = context.getBeanByName(bean
0839: .getInstanceName()
0840: + "Converter"); //NOI18N
0841: if (converterBean != null
0842: && converterBean.getInstance() instanceof Converter) {
0843: context.deleteBean(converterBean);
0844: }
0845: } catch (Exception e) {
0846: e.printStackTrace();
0847: }
0848: return Result.SUCCESS;
0849: }
0850:
0851: public Result selectManyBeanDeleted(DesignBean bean) {
0852: return selectOneBeanDeleted(bean);
0853: }
0854:
0855: protected ArrayList getExportedKeys(ResultSet rowSet,
0856: String catalog, String schema, String table) {
0857:
0858: if (!(rowSet instanceof RowSet)) {
0859: return null;
0860: }
0861: Connection c = null;
0862: try {
0863: c = getConnection((RowSet) rowSet);
0864: DatabaseMetaData dmd = c.getMetaData();
0865: ResultSet rs = dmd.getExportedKeys(catalog, schema, table);
0866: ArrayList list = new ArrayList();
0867: while (rs.next()) {
0868: list.add(rs.getString("PKCOLUMN_NAME")); //NOI18N
0869: }
0870: return list;
0871: } catch (Exception ex) {
0872: return null;
0873: } finally {
0874: // attempt to close, if fails, not an exceptional condition
0875: try {
0876: c.close();
0877: } catch (SQLException e) {
0878: }
0879: }
0880: }
0881:
0882: protected ArrayList getPrimaryKeys(ResultSet rowSet,
0883: String catalog, String schema, String table) {
0884:
0885: if (!(rowSet instanceof RowSet)) {
0886: return null;
0887: }
0888: Connection c = null;
0889: try {
0890: c = getConnection((RowSet) rowSet);
0891: DatabaseMetaData dmd = c.getMetaData();
0892: ResultSet rs = dmd.getPrimaryKeys(catalog, schema, table);
0893: ArrayList list = new ArrayList();
0894: while (rs.next()) {
0895: list.add(rs.getString("COLUMN_NAME")); //NOI18N
0896: }
0897: return list;
0898: } catch (Exception ex) {
0899: return null;
0900: } finally {
0901: // attempt to close, if fails, not an exceptional condition
0902: try {
0903: c.close();
0904: } catch (SQLException e) {
0905: }
0906: }
0907: }
0908:
0909: static protected Connection getConnection(RowSet rs)
0910: throws SQLException {
0911: try {
0912: if (rs.getDataSourceName() == null) {
0913: return DriverManager.getConnection(rs.getUrl(), rs
0914: .getUsername(), rs.getPassword());
0915: } else {
0916: Context ctx = new InitialContext();
0917: DataSource ds = (DataSource) ctx.lookup(rs
0918: .getDataSourceName());
0919: return ds.getConnection();
0920: }
0921: } catch (NamingException e) {
0922: SQLException sqle = new SQLException();
0923: sqle.initCause(e);
0924: throw sqle;
0925: }
0926: }
0927:
0928: /*
0929: * the following method is called by linkBeans for components that contain SelectItems
0930: */
0931: public Result selectOneLinkBeans(DesignBean targetBean,
0932: DesignBean sourceBean) {
0933: //DesignProperty selectionProperty = targetBean.getProperty("value");
0934:
0935: DesignBean selectItemsBean = null;
0936: int childCount = targetBean.getChildBeanCount();
0937: for (int i = 0; i < childCount; i++) {
0938: selectItemsBean = targetBean.getChildBean(i);
0939: if (targetBean.getChildBean(i).getInstance() instanceof UISelectItems) {
0940: break;
0941: }
0942: }
0943: FacesDesignProperty selectItemsValueproperty = (FacesDesignProperty) selectItemsBean
0944: .getProperty("value");
0945: Class sourceClass = sourceBean.getInstance().getClass();
0946: if (DataProvider.class.isAssignableFrom(sourceClass)) {
0947: FacesDesignContext fdc = (FacesDesignContext) targetBean
0948: .getDesignContext();
0949: DataProvider provider = (DataProvider) sourceBean
0950: .getInstance();
0951: FieldKey[] fieldKeys = provider.getFieldKeys();
0952:
0953: // Find a field of type Integer for value and String for display
0954: if (fieldKeys != null && fieldKeys.length > 0) {
0955: String valueField = null;
0956: String displayField = null;
0957: Class valueFieldType = null;
0958: for (int i = 0; i < fieldKeys.length; i++) {
0959: if ((valueField == null)
0960: && provider.getType(fieldKeys[i])
0961: .isAssignableFrom(Integer.class)) {
0962: valueField = fieldKeys[i].getFieldId();
0963: valueFieldType = provider.getType(fieldKeys[i]);
0964: }
0965: if ((displayField == null)
0966: && provider.getType(fieldKeys[i])
0967: .isAssignableFrom(String.class)) {
0968: displayField = fieldKeys[i].getFieldId();
0969: }
0970: }
0971: if (valueField == null) {
0972: valueField = fieldKeys[0].getFieldId();
0973: valueFieldType = provider.getType(fieldKeys[0]);
0974: }
0975: if (displayField == null) {
0976: displayField = fieldKeys[0].getFieldId();
0977: }
0978: StringBuffer expr = new StringBuffer();
0979: expr.append("#{");
0980: expr.append(fdc.getReferenceName());
0981: expr.append(".");
0982: expr.append(sourceBean.getInstanceName());
0983: expr.append(".options['");
0984: expr.append(valueField);
0985: expr.append(",");
0986: expr.append(displayField);
0987: expr.append("']}");
0988: ValueBinding vb = fdc.getFacesContext()
0989: .getApplication().createValueBinding(
0990: expr.toString());
0991: selectItemsValueproperty.setValueBinding(vb);
0992: return Result.SUCCESS;
0993: }
0994: return Result.FAILURE;
0995: }
0996: /*if ( isResultSetClass( sourceBean.getInstance().getClass() ) ) {
0997: try {
0998: // if cachedRowSetDataProvider, switch the sourceBean to
0999: // it's rowset.
1000: if ( isCachedRowSetDP( sourceBean.getInstance() ) ) {
1001: DesignBean db = findCachedRowSetBean( sourceBean) ;
1002: if ( db != null ) {
1003: sourceBean = db ;
1004: }
1005: }
1006:
1007: ResultMessage[] messages = new ResultMessage[1];
1008: DisplayAction[] actions = new DisplayAction[2];
1009: messages[0] = new ResultMessage(ResultMessage.TYPE_INFORMATION,
1010: bundle.getMessage("selItemLinkBeanPrompt", sourceBean.getInstanceName()), //NOI18N
1011: bundle.getMessage("dbBindSelItemClarify")); //NOI18N
1012: final DesignBean tb = targetBean;
1013: final DesignBean sb = sourceBean;
1014: actions[0] = new BasicDisplayAction(bundle.getMessage("fillList")) { //NOI18N
1015: public Result invoke() {
1016: try {
1017: ResultSet rs = (ResultSet)sb.getInstance();
1018: if (rs != null) {
1019: ResultSetMetaData rsmd = rs.getMetaData();
1020: if (rsmd.getColumnCount() >= 1) {
1021: //default to first column for value and no label or desc
1022: //but maybe we can do better
1023: int valueColumnNum = -1;
1024: int labelColumnNum = -1;
1025: // use the table from the first column
1026: String catalog = rsmd.getCatalogName(1);
1027: String schema = rsmd.getSchemaName(1);
1028: String table = rsmd.getTableName(1);
1029: ArrayList list = getExportedKeys(rs, catalog, schema, table);
1030: for (int i = 1; i <= rsmd.getColumnCount(); i++) {
1031: if (list.contains(rsmd.getColumnName(i))) {
1032: valueColumnNum = i;
1033: break;
1034: }
1035: }
1036: if (valueColumnNum == -1) {
1037: list = getPrimaryKeys(rs, catalog, schema, table);
1038: for (int i = 1; i <= rsmd.getColumnCount(); i++) {
1039: if (list.contains(rsmd.getColumnName(i))) {
1040: valueColumnNum = i;
1041: break;
1042: }
1043: }
1044: }
1045: if (valueColumnNum == -1) {
1046: valueColumnNum = 1;
1047: }
1048: table = rsmd.getTableName(valueColumnNum);
1049: String column = rsmd.getColumnName(valueColumnNum);
1050:
1051: //if value is not a character type, look for first char type
1052: //and use that column as a label
1053:
1054: String labelColumn = null;
1055: int valueType = rsmd.getColumnType(valueColumnNum);
1056: if (valueType != Types.CHAR && valueType != Types.LONGVARCHAR
1057: && valueType != Types.VARCHAR) {
1058: labelColumnNum = findAppropriateColumn(rsmd,
1059: new int[][] {
1060: {
1061: Types.CHAR, Types.VARCHAR}
1062: , {
1063: Types.LONGVARCHAR}
1064: });
1065: }
1066: if (labelColumnNum != -1) {
1067: labelColumn = rsmd.getColumnName(labelColumnNum);
1068: }
1069: // build the value
1070: String outerName =
1071: ((FacesDesignContext)sb.getDesignContext()).getReferenceName();
1072: String value = "#{" + outerName + "." + //NOI18N
1073: sb.getInstanceName() + ".selectItems['" + column; //NOI18N
1074: if (labelColumnNum != -1) {
1075: value += "," + labelColumn; //NOI18N
1076: }
1077: value += "']}"; //NOI18N
1078: // String dtvalue = "[" + table + "." + column + "]";
1079: DesignBean selectItems = null;
1080: DesignBean[] children = tb.getChildBeans();
1081: if (children != null && children.length > 0) {
1082: for (int i = 0; i < children.length; i++) {
1083: if (children[i].getInstance() instanceof UISelectItems) {
1084: selectItems = children[i];
1085: break;
1086: }
1087: }
1088: }
1089: if (selectItems == null) {
1090: selectItems = tb.getDesignContext().createBean(
1091: UISelectItems.class.getName(), tb, null);
1092: selectItems.setInstanceName(tb.getInstanceName()
1093: + "SelectItems", true); //NOI18N
1094: }
1095: ///MBOHM for 6194849, no harm in calling this line here
1096: value = maybeSetupDefaultSelectItems(selectItems, value);
1097: selectItems.getProperty("value").setValue(value); //NOI18N
1098: //MBOHM 6194849 //maybeSetupConverter(selectItems, valueType);
1099: return Result.SUCCESS;
1100: }
1101: }
1102: } catch (SQLException e) {
1103: e.printStackTrace();
1104: }
1105: return Result.FAILURE;
1106: }
1107: };
1108: actions[1] = new BasicDisplayAction(bundle.getMessage("bindToSel")) { //NOI18N
1109: public Result invoke() {
1110: try {
1111: ResultSet rs = (ResultSet)sb.getInstance();
1112: if (rs != null) {
1113: ResultSetMetaData rsmd = rs.getMetaData();
1114: if (rsmd.getColumnCount() >= 1) {
1115: String table = rsmd.getTableName(1);
1116: String column = rsmd.getColumnName(1);
1117: // build the value
1118: String outerName =
1119: ((FacesDesignContext)sb.getDesignContext()).getReferenceName();
1120: String value = "#{" + outerName + "." + //NOI18N
1121: sb.getInstanceName() + ".currentRow['" + column + "']}"; //NOI18N
1122: tb.getProperty("value").setValue(value); //NOI18N
1123: }
1124: // MBOHM 6194849
1125: //DesignBean[] siKids = tb.getChildBeans();
1126: //for (int i = 0; i < siKids.length; i++) {
1127: // maybeSetupConverter(siKids[i], 0);
1128: //}
1129: }
1130: } catch (SQLException e) {
1131: e.printStackTrace();
1132: }
1133: return Result.SUCCESS;
1134: }
1135: };
1136: return new Result(true, messages, actions);
1137: } catch (Exception e) {
1138: e.printStackTrace();
1139: return Result.FAILURE;
1140: }
1141: }*/
1142: return Result.SUCCESS;
1143: }
1144:
1145: public Result selectManyLinkBeans(DesignBean targetBean,
1146: DesignBean sourceBean) {
1147:
1148: // if cachedRowSetDataProvider, switch the sourceBean to
1149: // it's rowset.
1150: if (isCachedRowSetDP(sourceBean.getInstance())) {
1151: DesignBean db = findCachedRowSetBean(sourceBean);
1152: if (db != null) {
1153: sourceBean = db;
1154: }
1155: }
1156:
1157: if (sourceBean.getInstance() instanceof ResultSet) {
1158: DesignBean tb = targetBean;
1159: DesignBean sb = sourceBean;
1160: try {
1161: ResultSet rs = (ResultSet) sb.getInstance();
1162: if (rs != null) {
1163: ResultSetMetaData rsmd = rs.getMetaData();
1164: if (rsmd.getColumnCount() >= 1) {
1165: /*
1166: * default to first column for value and no label or desc
1167: * but maybe we can do better
1168: */
1169: int valueColumnNum = -1;
1170: int labelColumnNum = -1;
1171: // use the table from the first column
1172: String catalog = rsmd.getCatalogName(1);
1173: String schema = rsmd.getSchemaName(1);
1174: String table = rsmd.getTableName(1);
1175: ArrayList list = getExportedKeys(rs, catalog,
1176: schema, table);
1177: for (int i = 1; i <= rsmd.getColumnCount(); i++) {
1178: if (list.contains(rsmd.getColumnName(i))) {
1179: valueColumnNum = i;
1180: break;
1181: }
1182: }
1183: if (valueColumnNum == -1) {
1184: list = getPrimaryKeys(rs, catalog, schema,
1185: table);
1186: for (int i = 1; i <= rsmd.getColumnCount(); i++) {
1187: if (list
1188: .contains(rsmd.getColumnName(i))) {
1189: valueColumnNum = i;
1190: break;
1191: }
1192: }
1193: }
1194: if (valueColumnNum == -1) {
1195: valueColumnNum = 1;
1196: }
1197: table = rsmd.getTableName(valueColumnNum);
1198: String column = rsmd
1199: .getColumnName(valueColumnNum);
1200:
1201: /* if value is not a character type, look for first char type
1202: * and use that column as a label
1203: */
1204: String labelColumn = null;
1205: int valueType = rsmd
1206: .getColumnType(valueColumnNum);
1207: if (valueType != Types.CHAR
1208: && valueType != Types.LONGVARCHAR
1209: && valueType != Types.VARCHAR) {
1210: labelColumnNum = findAppropriateColumn(
1211: rsmd,
1212: new int[][] {
1213: { Types.CHAR, Types.VARCHAR },
1214: { Types.LONGVARCHAR } });
1215: }
1216: if (labelColumnNum != -1) {
1217: labelColumn = rsmd
1218: .getColumnName(labelColumnNum);
1219: }
1220: // build the value
1221: String outerName = ((FacesDesignContext) sb
1222: .getDesignContext()).getReferenceName();
1223: String value = "#{" + outerName + "."
1224: + //NOI18N
1225: sb.getInstanceName() + ".selectItems['"
1226: + column; //NOI18N
1227: if (labelColumnNum != -1) {
1228: value += "," + labelColumn; //NOI18N
1229: }
1230: value += "']}"; //NOI18N
1231: // String dtvalue = "[" + table + "." + column + "]";
1232: DesignBean selectItems = null;
1233: DesignBean[] children = tb.getChildBeans();
1234: if (children != null && children.length > 0) {
1235: for (int i = 0; i < children.length; i++) {
1236: if (children[i].getInstance() instanceof UISelectItems) {
1237: selectItems = children[i];
1238: break;
1239: }
1240: }
1241: }
1242: if (selectItems == null) {
1243: selectItems = tb.getDesignContext()
1244: .createBean(
1245: UISelectItems.class
1246: .getName(), tb,
1247: null);
1248: selectItems.setInstanceName(tb
1249: .getInstanceName()
1250: + "SelectItems", true); //NOI18N
1251: }
1252: //MBOHM for 6194849, no harm in calling this line here
1253: value = maybeSetupDefaultSelectItems(
1254: selectItems, value);
1255: selectItems.getProperty("value")
1256: .setValue(value); //NOI18N
1257: //MBOHM 6194849 //maybeSetupConverter(selectItems, valueType);
1258: return Result.SUCCESS;
1259: }
1260: }
1261: } catch (SQLException e) {
1262: e.printStackTrace();
1263: }
1264: return Result.FAILURE;
1265: }
1266: return Result.SUCCESS;
1267: }
1268:
1269: public static String maybeSetupDefaultSelectItems(
1270: DesignBean selectItemsBean, String valueExpr) {
1271: try {
1272: if (valueExpr != null && !"".equals(valueExpr)) {
1273: if (selectItemsBean.getInstance() instanceof UISelectItems) {
1274: // find the parent UISelectOne or UISelectMany bean
1275: DesignBean selectCompBean = selectItemsBean
1276: .getBeanParent();
1277: if (selectCompBean != null
1278: && (selectCompBean.getInstance() instanceof UISelectOne || selectCompBean
1279: .getInstance() instanceof UISelectMany)) {
1280:
1281: DesignContext context = selectCompBean
1282: .getDesignContext();
1283: // check for existance of default items array - and nuke it
1284: String itemsName = selectCompBean
1285: .getInstanceName()
1286: + "DefaultItems"; //NOI18N
1287: DesignBean itemsBean = context
1288: .getBeanByName(itemsName);
1289: if (itemsBean != null) {
1290: // check if this value expression points at the default items already
1291: // if not, then delete them...
1292: //JOE: this exposes an insync bug in 'resolveBindingExpr'
1293: //JOE: so the below fix works without hitting the bug
1294: // if (context instanceof FacesDesignContext) {
1295: // Object o = ((FacesDesignContext)context).resolveBindingExpr(valueExpr);
1296: // if (o != itemsBean.getInstance()) {
1297: // context.deleteBean(itemsBean);
1298: // }
1299: // }
1300: String[] vx = valueExpr.split("\\.");
1301: if (vx.length > 0) {
1302: String name = vx[vx.length - 1];
1303: name = name.substring(0,
1304: name.length() - 1);
1305: if (!name.equals(itemsBean
1306: .getInstanceName())) {
1307: context.deleteBean(itemsBean);
1308: }
1309: }
1310: }
1311: }
1312: }
1313: return valueExpr;
1314: } else if (selectItemsBean.getInstance() instanceof UISelectItems) {
1315: // find the parent UISelectOne or UISelectMany bean
1316: DesignBean selectCompBean = selectItemsBean
1317: .getBeanParent();
1318: if (selectCompBean != null
1319: && (selectCompBean.getInstance() instanceof UISelectOne || selectCompBean
1320: .getInstance() instanceof UISelectMany)) {
1321:
1322: DesignContext context = selectCompBean
1323: .getDesignContext();
1324: // check for existance / create and setup a default items array
1325: String itemsName = selectCompBean.getInstanceName()
1326: + "DefaultItems"; //NOI18N
1327: DesignBean itemsBean = context
1328: .getBeanByName(itemsName);
1329: if (itemsBean == null
1330: || !(itemsBean.getInstance() instanceof DefaultSelectItemsArray)) {
1331: itemsBean = context
1332: .createBean(
1333: DefaultSelectItemsArray.class
1334: .getName(), null, null);
1335: itemsBean.setInstanceName(itemsName, true); //NOI18N
1336: }
1337: if (context instanceof FacesDesignContext) {
1338: return "#{"
1339: + ((FacesDesignContext) context)
1340: .getReferenceName() + "."
1341: + itemsBean.getInstanceName() + "}"; //NOI18N
1342: }
1343: return "#{" + context.getDisplayName() + "."
1344: + itemsBean.getInstanceName() + "}"; //NOI18N
1345: }
1346: }
1347: } catch (Exception e) {
1348: e.printStackTrace();
1349: }
1350: return valueExpr;
1351: }
1352:
1353: public static void maybeSetupConverter(DesignBean selectItemsBean,
1354: int sqlDataType) {
1355: Class convClass = getConverterClass(sqlDataType);
1356: try {
1357: if (selectItemsBean.getInstance() instanceof UISelectItems) {
1358: // find the parent UISelectOne or UISelectMany bean
1359: DesignBean selectCompBean = selectItemsBean
1360: .getBeanParent();
1361: if (selectCompBean != null
1362: && (selectCompBean.getInstance() instanceof UISelectOne || selectCompBean
1363: .getInstance() instanceof UISelectMany)) {
1364:
1365: DesignContext context = selectItemsBean
1366: .getDesignContext();
1367: String convName = selectCompBean.getInstanceName()
1368: + "Converter"; //NOI18N
1369: DesignBean oldConvBeanByName = context
1370: .getBeanByName(convName);
1371: if (oldConvBeanByName != null) {
1372: context.deleteBean(oldConvBeanByName);
1373: }
1374:
1375: // if the value is not set...
1376: DesignProperty scValueProp = selectCompBean
1377: .getProperty("value"); //NOI18N
1378: if (scValueProp != null
1379: && (scValueProp.getValue() == null
1380: || scValueProp.getValueSource() == null || ""
1381: .equals(scValueProp
1382: .getValueSource()))) { //NOI18N
1383:
1384: // and no converter (or wrong type) is set...
1385: DesignProperty convProp = selectCompBean
1386: .getProperty("converter"); //NOI18N
1387: if (convProp != null) {
1388: Object convObj = convProp.getValue();
1389: if (convClass == null && convObj != null) {
1390: convProp.setValue(null);
1391: } else if (convClass != null
1392: && (convObj == null || !convClass
1393: .isAssignableFrom(convObj
1394: .getClass()))) {
1395: // we need to setup a new converter
1396: DesignBean convBean = context
1397: .createBean(
1398: convClass.getName(),
1399: null, null);
1400: convBean.setInstanceName(convName);
1401: if (convBean != null) {
1402: convProp.setValue(convBean
1403: .getInstance());
1404: }
1405: }
1406: }
1407: }
1408: }
1409: }
1410: } catch (Exception e) {
1411: e.printStackTrace();
1412: }
1413: }
1414:
1415: /**
1416: *
1417: * Pass in the java.sql.Types type returned by ResultSet.getColumnType()
1418: * True is returned if a converter is available or if a converter is not
1419: * needed.
1420: *
1421: * Note: The information is returned is a best guess. This will be further refined
1422: * post-RR. Also, more converters will be written post-RR.
1423: */
1424: public static boolean isConvertible(int sqlType) {
1425:
1426: switch (sqlType) {
1427:
1428: case Types.SMALLINT:
1429: case Types.INTEGER:
1430: case Types.TINYINT:
1431: case Types.BIGINT:
1432: case Types.BIT:
1433: case Types.BOOLEAN:
1434: case Types.DATE:
1435: case Types.TIME:
1436: case Types.TIMESTAMP:
1437: case Types.DECIMAL:
1438: case Types.NUMERIC:
1439: case Types.DOUBLE:
1440: case Types.REAL:
1441: case Types.FLOAT:
1442: case Types.CHAR:
1443: case Types.LONGVARCHAR:
1444: case Types.VARCHAR:
1445: return true;
1446:
1447: case Types.BINARY:
1448: case Types.BLOB:
1449: case Types.CLOB:
1450: case Types.DATALINK:
1451: case Types.DISTINCT:
1452: case Types.JAVA_OBJECT:
1453: case Types.LONGVARBINARY:
1454: case Types.NULL:
1455: case Types.OTHER:
1456: case Types.REF:
1457: case Types.STRUCT:
1458: case Types.VARBINARY:
1459: return false;
1460: }
1461:
1462: return false;
1463: }
1464:
1465: /**
1466: * Pass in the java.sql.Types type returned by ResultSet.getColumnType()
1467: * The appropriate faces converter class is returned. If null is returned,
1468: * it may be because no converter exists or because a converter is not
1469: * needed. If you want to know which case it is, call isConvertible(int sqlType)
1470: * this will return true if a converter is available or a converter is not needed.
1471: *
1472: * The converter choice is based on the JDBC 3.0 Specification, Appendix B,
1473: * "Data Type Conversion Tables", Table B-1.
1474: */
1475: public static Class getConverterClass(int sqlType) {
1476:
1477: switch (sqlType) {
1478:
1479: case Types.SMALLINT:
1480: return javax.faces.convert.ShortConverter.class;
1481:
1482: case Types.INTEGER:
1483: return javax.faces.convert.IntegerConverter.class;
1484:
1485: case Types.TINYINT:
1486: return javax.faces.convert.ByteConverter.class;
1487:
1488: case Types.BIGINT:
1489: return javax.faces.convert.LongConverter.class;
1490:
1491: case Types.BIT:
1492: case Types.BOOLEAN:
1493: return javax.faces.convert.BooleanConverter.class;
1494:
1495: case Types.DATE:
1496: return com.sun.rave.faces.converter.SqlDateConverter.class;
1497:
1498: case Types.TIME:
1499: return com.sun.rave.faces.converter.SqlTimeConverter.class;
1500:
1501: case Types.TIMESTAMP:
1502: return com.sun.rave.faces.converter.SqlTimestampConverter.class;
1503:
1504: case Types.DECIMAL:
1505: case Types.NUMERIC:
1506: return javax.faces.convert.BigDecimalConverter.class;
1507:
1508: case Types.DOUBLE:
1509: case Types.FLOAT:
1510: return javax.faces.convert.DoubleConverter.class;
1511:
1512: case Types.REAL:
1513: return javax.faces.convert.FloatConverter.class;
1514:
1515: case Types.BINARY:
1516: case Types.CHAR:
1517: case Types.LONGVARCHAR:
1518: case Types.VARCHAR:
1519: case Types.BLOB:
1520: case Types.CLOB:
1521: case Types.DATALINK:
1522: case Types.DISTINCT:
1523: case Types.JAVA_OBJECT:
1524: case Types.LONGVARBINARY:
1525: case Types.NULL:
1526: case Types.OTHER:
1527: case Types.REF:
1528: case Types.STRUCT:
1529: case Types.VARBINARY:
1530: return null;
1531: }
1532:
1533: return null;
1534: }
1535:
1536: /**
1537: * findAppropriateColumn finds an appropriate column to bind to in a resultset.
1538: * Pass an array of SQL types (java.sql.Types) and this method will return
1539: * the first column in the resultset that matches any of the types in the
1540: * array. If some types have a higher priority, use the version of
1541: * findAppropriateColumn that takes an array of array types. If a match is found,
1542: * the column position (1 based) in the resultset will be returned. If no match
1543: * is found, -1 is returned.
1544: */
1545: protected int findAppropriateColumn(ResultSetMetaData rsmd,
1546: int[] types) throws SQLException {
1547: int[][] _types = new int[1][];
1548: _types[0] = types;
1549: return findAppropriateColumn(rsmd, _types);
1550: }
1551:
1552: /**
1553: * findAppropriateColumn finds an appropriate column to bind to in a resultset.
1554: * Pass an array of arrays of SQL types (java.sql.Types). This method will first
1555: * attempt to match any of the types in the first array. If no columns match, it
1556: * will proceed to the next array. If a match is found, the column position (1 based)
1557: * in the resultset will be returned. If no match is found, -1 is returned.
1558: *
1559: * Example:
1560: *
1561: * private static final int[][] TYPES = new int[][] {
1562: * {Types.INTEGER, Types.SMALLINT}, // First try to match on these
1563: * {Types.BIT, Types.TINYINT} // If no match above, try to match on these
1564: * };
1565: *
1566: * public Result linkBeans(DesignBean targetBean, DesignBean sourceBean) {
1567: * return linkBeans(targetBean, sourceBean, TYPES);
1568: * }
1569: */
1570: protected int findAppropriateColumn(ResultSetMetaData rsmd,
1571: int[][] types) throws SQLException {
1572: for (int i = 0; i < types.length; i++) {
1573: for (int j = 1; j <= rsmd.getColumnCount(); j++) {
1574: for (int k = 0; k < types[i].length; k++) {
1575: if (rsmd.getColumnType(j) == types[i][k]) {
1576: return j;
1577: }
1578: }
1579: }
1580: }
1581: return -1;
1582: }
1583:
1584: /*
1585: * I know this SUCKS and is a HACK, but with the way all of the subclasses implement linkBeans()
1586: * and the fact that there is no consumed ability to the event, I'm doing it this way to be safe.
1587: * If I dont, it may end up that something is linked twice and can't afford that at T-1.5 of RR :(
1588: * I most likely could have just made sure that each class did or did not have the properties
1589: * in question, but brain not working that well at moment, and this is what I can deal with at
1590: * moment.
1591: *
1592: * HACKS
1593: * - doConverterOrValidatorLinkBeans
1594: * - isConverterOrValidatorLinkBeans
1595: * - and all there callers
1596: *
1597: * @param targetBean
1598: * @param sourceBean
1599: * @return
1600: */
1601: public Result linkConverterOrValidatorBeans(DesignBean targetBean,
1602: DesignBean sourceBean) {
1603:
1604: try {
1605: DesignBean rootBean = sourceBean.getDesignContext()
1606: .getRootContainer();
1607: DesignProperty property;
1608: if (sourceBean.getInstance() instanceof Converter) {
1609: property = targetBean.getProperty("converter"); // NOI18N
1610: if (property != null
1611: && property.getPropertyDescriptor() != null
1612: && Converter.class.isAssignableFrom(property
1613: .getPropertyDescriptor()
1614: .getPropertyType())) {
1615: property.setValue(sourceBean.getInstance());
1616: if (sourceBean.getInstance() instanceof NumberConverter) {
1617: return new CustomizerResult(sourceBean,
1618: new NumberConverterCustomizer());
1619: }
1620: return Result.SUCCESS;
1621: }
1622: }
1623: if (sourceBean.getInstance() instanceof Validator) {
1624: property = targetBean.getProperty("validator"); // NOI18N
1625: if (property != null
1626: && property.getPropertyDescriptor() != null
1627: && MethodBinding.class
1628: .isAssignableFrom(property
1629: .getPropertyDescriptor()
1630: .getPropertyType())) {
1631: FacesDesignContext fctx = (FacesDesignContext) targetBean
1632: .getDesignContext();
1633: String validateBinding = fctx.getBindingExpr(
1634: sourceBean, ".validate"); // NOI18N
1635: Application app = fctx.getFacesContext()
1636: .getApplication();
1637: MethodBinding mb = app.createMethodBinding(
1638: validateBinding, new Class[] {
1639: FacesContext.class,
1640: UIComponent.class, Object.class });
1641: property.setValue(mb);
1642: return Result.SUCCESS;
1643: }
1644: }
1645: } catch (Exception x) {
1646: x.printStackTrace();
1647: return Result.FAILURE;
1648: }
1649: return Result.SUCCESS;
1650: }
1651:
1652: public boolean canLinkConverterOrValidatorBeans(
1653: DesignBean targetBean, Class sourceClass) {
1654:
1655: PropertyDescriptor propertyDescriptor;
1656: if (Converter.class.isAssignableFrom(sourceClass)) {
1657: propertyDescriptor = getPropertyDescriptorNamed("converter"); // NOI18N
1658: if (propertyDescriptor != null
1659: && Converter.class
1660: .isAssignableFrom(propertyDescriptor
1661: .getPropertyType())) {
1662: return true;
1663: }
1664: }
1665: if (Validator.class.isAssignableFrom(sourceClass)) {
1666: propertyDescriptor = getPropertyDescriptorNamed("validator"); // NOI18N
1667: if (propertyDescriptor != null
1668: && MethodBinding.class
1669: .isAssignableFrom(propertyDescriptor
1670: .getPropertyType())) {
1671: return true;
1672: }
1673: }
1674: return false;
1675: }
1676:
1677: public boolean canLinkConverterOrValidatorBeans(
1678: DesignBean targetBean, DesignBean sourceBean) {
1679:
1680: if (sourceBean == null || sourceBean.getInstance() == null) {
1681: return false;
1682: }
1683: return canLinkConverterOrValidatorBeans(targetBean, sourceBean
1684: .getInstance().getClass());
1685: }
1686:
1687: /***
1688: * methods for using cachedRowSets and CachedRowSetDataProviders
1689: */
1690: public static boolean isCachedRowSetDP(Object db) {
1691: return (db instanceof CachedRowSetDataProvider);
1692: }
1693:
1694: public static boolean isResultSetClass(Class sourceClass) {
1695: return ResultSet.class.isAssignableFrom(sourceClass)
1696: || CachedRowSetDataProvider.class
1697: .isAssignableFrom(sourceClass);
1698: }
1699:
1700: // For performance improvement. No need to get all the contexts in the project
1701: private static DesignContext[] getDesignContexts(
1702: DesignBean designBean) {
1703: DesignProject designProject = designBean.getDesignContext()
1704: .getProject();
1705: DesignContext[] contexts;
1706: if (designProject instanceof FacesDesignProject) {
1707: contexts = ((FacesDesignProject) designProject)
1708: .findDesignContexts(new String[] { "request",
1709: "session", "application" });
1710: } else {
1711: contexts = new DesignContext[0];
1712: }
1713: DesignContext[] designContexts = new DesignContext[contexts.length + 1];
1714: designContexts[0] = designBean.getDesignContext();
1715: System.arraycopy(contexts, 0, designContexts, 1,
1716: contexts.length);
1717: return designContexts;
1718: }
1719:
1720: /**
1721: * given a srcBean of type CachedRowSetDataProvider, find it's
1722: * CachedRowSet designBean.
1723: * return null if not found.
1724: */
1725: public static DesignBean findCachedRowSetBean(DesignBean dpBean) {
1726: if (!(dpBean.getInstance() instanceof CachedRowSetDataProvider))
1727: return null;
1728:
1729: // change sourceBean to the DesignBean for the dataprovider's cachedRowSet property.
1730: DesignProperty prop = dpBean.getProperty("cachedRowSet");
1731: if (prop == null)
1732: return null;
1733:
1734: Object rowSetInstance = prop.getValue();
1735: if (!(rowSetInstance instanceof RowSet))
1736: return null;
1737:
1738: // now loop through all contexts to find the DesignBean that wraps this
1739: // CachedRowSet.
1740: //DesignContext[] contexts = dpBean.getDesignContext().getProject().getDesignContexts();
1741: DesignContext[] contexts = getDesignContexts(dpBean);
1742:
1743: DesignBean rowSetBean;
1744: for (int i = 0, n = contexts.length; i < n; i++) {
1745: rowSetBean = contexts[i].getBeanForInstance(rowSetInstance);
1746: if (rowSetBean != null) {
1747: return rowSetBean;
1748: }
1749: }
1750: return null;
1751: }
1752: }
|