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.std.table;
0042:
0043: import java.io.File;
0044: import java.io.IOException;
0045: import java.io.PrintStream;
0046: import java.net.URL;
0047: import java.sql.ResultSet;
0048: import java.sql.ResultSetMetaData;
0049: import java.util.ArrayList;
0050: import java.util.List;
0051: import javax.faces.application.Application;
0052: import javax.faces.component.UIColumn;
0053: import javax.faces.component.UICommand;
0054: import javax.faces.component.UISelectItems;
0055: import javax.faces.component.html.HtmlCommandButton;
0056: import javax.faces.component.html.HtmlCommandLink;
0057: import javax.faces.component.html.HtmlMessage;
0058: import javax.faces.component.html.HtmlOutputText;
0059: import javax.faces.component.html.HtmlPanelGrid;
0060: import javax.faces.component.html.HtmlPanelGroup;
0061: import javax.faces.component.html.HtmlSelectOneMenu;
0062: import javax.faces.component.html.HtmlSelectOneRadio;
0063: import javax.faces.context.FacesContext;
0064: import javax.faces.el.ReferenceSyntaxException;
0065: import javax.faces.el.ValueBinding;
0066: import javax.sql.RowSet;
0067: import com.sun.rave.faces.data.DefaultSelectItemsArray;
0068: import com.sun.rave.faces.data.CachedRowSetDataModel;
0069: import org.netbeans.modules.visualweb.faces.dt.util.ComponentBundle;
0070: import com.sun.rave.designtime.DesignBean;
0071: import com.sun.rave.designtime.DesignContext;
0072: import com.sun.rave.designtime.DesignEvent;
0073: import com.sun.rave.designtime.DesignProject;
0074: import com.sun.rave.designtime.DesignProperty;
0075: import com.sun.rave.designtime.Position;
0076: import com.sun.rave.designtime.faces.FacesDesignBean;
0077: import com.sun.rave.designtime.faces.FacesDesignContext;
0078: import com.sun.rave.designtime.faces.FacesDesignProject;
0079:
0080: public class HtmlDataTableState {
0081:
0082: private static final ComponentBundle bundle = ComponentBundle
0083: .getBundle(HtmlDataTableState.class);
0084:
0085: public static final String DEFAULT_VAR_NAME = "currentRow"; //NOI18N
0086: private static final String COLUMN_ITEM_TEXT = bundle
0087: .getMessage("column"); //NOI18N
0088: private static final String JSFEL_START = "#{"; //NOI18N
0089: private static final String JSFEL_END = "}"; //NOI18N
0090: private static final String JSFEL_OPENQUOT = "['"; //NOI18N
0091: private static final String JSFEL_CLOSEQUOT = "']"; //NOI18N
0092: private static final String DOT = "."; //NOI18N
0093: private static final String ACTION_LIVE_EVENT = "action"; //NOI18N
0094: private static final String[] PAGING_HANDLER_SUFFIXES = {
0095: "_firstPageAction", "_previousPageAction",
0096: "_nextPageAction", "_lastPageAction" }; //NOI18N
0097:
0098: private static final String STYLE_CLASS_HEADER = "list-paging-header"; //NOI18N
0099: private static final String STYLE_CLASS_FOOTER = "list-paging-footer"; //NOI18N
0100:
0101: private static final String DEFAULT_FIRST_TEXT = "|<"; //NOI18N
0102: private static final String DEFAULT_PREVIOUS_TEXT = "<-"; //NOI18N
0103: private static final String DEFAULT_NEXT_TEXT = "->"; //NOI18N
0104: private static final String DEFAULT_LAST_TEXT = ">|"; //NOI18N
0105: private static final String DEFAULT_FIRST_URL = "resources/paging_first.gif"; //NOI18N
0106: private static final String DEFAULT_PREVIOUS_URL = "resources/paging_previous.gif"; //NOI18N
0107: private static final String DEFAULT_NEXT_URL = "resources/paging_next.gif"; //NOI18N
0108: private static final String DEFAULT_LAST_URL = "resources/paging_last.gif"; //NOI18N
0109: private static final String DEFAULT_FIRST_IMG = "paging_first.gif"; //NOI18N
0110: private static final String DEFAULT_PREVIOUS_IMG = "paging_previous.gif"; //NOI18N
0111: private static final String DEFAULT_NEXT_IMG = "paging_next.gif"; //NOI18N
0112: private static final String DEFAULT_LAST_IMG = "paging_last.gif"; //NOI18N
0113:
0114: static final String TOP = bundle.getMessage("top"); //NOI18N
0115: static final String BOTTOM = bundle.getMessage("bottom"); //NOI18N
0116: static final String TOP_AND_BOTTOM = bundle
0117: .getMessage("topAndBottom"); //NOI18N
0118: static final String BUTTON_TEXT = bundle.getMessage("navBtnText"); //NOI18N
0119: static final String BUTTON_IMAGE = bundle.getMessage("navBtnImage"); //NOI18N
0120: static final String BUTTON_NONE = bundle
0121: .getMessage("navBtnNotDispl"); //NOI18N
0122: static final String ALIGN_CENTER = bundle.getMessage("center"); //NOI18N
0123: static final String ALIGN_LEFT = bundle.getMessage("left"); //NOI18N
0124: static final String ALIGN_RIGHT = bundle.getMessage("right"); //NOI18N
0125:
0126: private DesignBean tableBean;
0127:
0128: public HtmlDataTableState(DesignBean tableBean) {
0129: this .tableBean = tableBean;
0130: loadState();
0131: }
0132:
0133: public DesignBean getTableBean() {
0134: return this .tableBean;
0135: }
0136:
0137: public static String maybeGenerateRowsetColumns(
0138: DesignBean tableBean, String valueExpr) {
0139: DesignContext context = tableBean.getDesignContext();
0140: if (context instanceof FacesDesignContext) {
0141: FacesDesignContext fcontext = (FacesDesignContext) context;
0142: Object o = fcontext.resolveBindingExpr(valueExpr);
0143: if (o instanceof RowSet) {
0144: // ok - we know the user has bound to a RowSet, so do the necessary "magic", and
0145: // return the value expr that points to the CachedRowSetDataModel
0146: RowSet rs = (RowSet) o;
0147: HtmlDataTableState state = new HtmlDataTableState(
0148: tableBean);
0149: state.setSourceInstance(rs);
0150: state.refreshColumnInfo();
0151: valueExpr = state.saveStateExceptModelValueExpr();
0152: }
0153: }
0154: return valueExpr;
0155: }
0156:
0157: /////////////////////////////////// CLASS STRUCTURES ///////////////////////////////////////////
0158:
0159: //////Columns tab///////
0160: //private String instanceName; //instance name to be persisted in source code (such as dataTable1) of the tableBean's underlying HtmlDataTable instance
0161: private DesignBean sourceBean; //the live bean chosen as the source of data for the table
0162: public String varName; //the value of the var attribute for this table in the JSP
0163: public ResultSetInfo rsinfo; //information about a ResultSet, if the sourceBean is of that type
0164: public DisplayInfo display = new DisplayInfo(); //information about the columns to be displayed
0165: private DesignBean savedSourceBean; //the sourceBean set by loadState
0166:
0167: ///////Paging tab///////
0168: public PagingInfo paging = new PagingInfo(); //information gathered from the Paging tab
0169:
0170: public void setSourceBean(DesignBean bean) {
0171: sourceBean = bean;
0172: }
0173:
0174: public void refreshColumnInfo() {
0175: display.clearColumns();
0176: if (getSourceInstance() instanceof ResultSet) {
0177: if (rsinfo == null) {
0178: rsinfo = new ResultSetInfo();
0179: }
0180: rsinfo.refreshColumns();
0181: for (int i = 0; i < rsinfo.getColumnCount(); i++) {
0182: display.addColumn(rsinfo.getColumn(i));
0183: }
0184: } else {
0185: rsinfo = null;
0186: display.addNewColumn();
0187: }
0188: }
0189:
0190: public DesignBean getSourceBean() {
0191: return sourceBean;
0192: }
0193:
0194: public void setSourceInstance(Object sourceInst) {
0195: DesignBean designBean = getDesignBeanForSourceInstance(sourceInst);
0196: setSourceBean(designBean);
0197: }
0198:
0199: public Object getSourceInstance() {
0200: return sourceBean == null ? null : sourceBean.getInstance();
0201: }
0202:
0203: public DesignBean getSavedSourceBean() {
0204: return savedSourceBean;
0205: }
0206:
0207: // For performance improvement. No need to get all the contexts in the project
0208: private DesignContext[] getDesignContexts(DesignBean designBean) {
0209: DesignProject designProject = designBean.getDesignContext()
0210: .getProject();
0211: DesignContext[] contexts;
0212: if (designProject instanceof FacesDesignProject) {
0213: contexts = ((FacesDesignProject) designProject)
0214: .findDesignContexts(new String[] { "request",
0215: "session", "application" });
0216: } else {
0217: contexts = new DesignContext[0];
0218: }
0219: DesignContext[] designContexts = new DesignContext[contexts.length + 1];
0220: designContexts[0] = designBean.getDesignContext();
0221: System.arraycopy(contexts, 0, designContexts, 1,
0222: contexts.length);
0223: return designContexts;
0224: }
0225:
0226: private DesignBean getDesignBeanForSourceInstance(Object sourceInst) {
0227: if (sourceInst == null) {
0228: return null;
0229: }
0230: DesignBean designBean = null;
0231: //DesignContext[] contexts = tableBean.getDesignContext().getProject().getDesignContexts();
0232: DesignContext[] contexts = getDesignContexts(tableBean);
0233: for (int i = 0; i < contexts.length; i++) {
0234: designBean = contexts[i].getBeanForInstance(sourceInst);
0235: if (designBean != null) {
0236: break;
0237: }
0238: }
0239: return designBean;
0240: }
0241:
0242: private String getStrippedSourceBeanValueRef() {
0243: if (sourceBean == null) {
0244: return null;
0245: }
0246: DesignContext context = sourceBean.getDesignContext();
0247: String outer = ((FacesDesignContext) context)
0248: .getReferenceName();
0249: return outer + DOT + sourceBean.getInstanceName();
0250: }
0251:
0252: public class ResultSetInfo {
0253: private List resultSetColumnList = new ArrayList();
0254:
0255: public void refreshColumns() {
0256: clearColumns();
0257: Object sourceInst = getSourceInstance();
0258: if (!(sourceInst instanceof ResultSet)) {
0259: return;
0260: }
0261: ResultSet rs = (ResultSet) sourceInst;
0262: try {
0263: ResultSetMetaData rsmd = rs.getMetaData();
0264: int cols = rsmd.getColumnCount();
0265: for (int c = 1; c <= cols; c++) {
0266: ResultSetColumn rsc = new ResultSetColumn();
0267: rsc.tableName = rsmd.getTableName(c);
0268: rsc.columnName = rsmd.getColumnName(c);
0269: //rsc.columnClassName = rsmd.getColumnClassName(c);
0270: //rsc.columnSqlType = rsmd.getColumnType(c);
0271: //rsc.columnSqlTypeName = rsmd.getColumnTypeName(c);
0272: addColumn(rsc);
0273: }
0274: } catch (Exception x) {
0275: System.err
0276: .println("HtmlDataTableState.ResultSetInfo.refreshColumns(): probable ResultSetMetaData problem:"); //NOI18N
0277: x.printStackTrace();
0278: }
0279: }
0280:
0281: public ResultSetColumn createColumn() {
0282: return new ResultSetColumn();
0283: }
0284:
0285: public void addColumn(ResultSetColumn rsc) {
0286: resultSetColumnList.add(rsc);
0287: }
0288:
0289: public void removeColumn(ResultSetColumn rsc) {
0290: resultSetColumnList.remove(rsc);
0291: }
0292:
0293: public void clearColumns() {
0294: resultSetColumnList.clear();
0295: }
0296:
0297: public ResultSetColumn[] getColumns() {
0298: return (ResultSetColumn[]) resultSetColumnList
0299: .toArray(new ResultSetColumn[resultSetColumnList
0300: .size()]);
0301: }
0302:
0303: public int getColumnCount() {
0304: return resultSetColumnList.size();
0305: }
0306:
0307: public ResultSetColumn getColumn(int index) {
0308: return (ResultSetColumn) resultSetColumnList.get(index);
0309: }
0310: }
0311:
0312: public class ResultSetColumn {
0313: public String tableName;
0314: public String columnName;
0315:
0316: //public String columnClassName;
0317: //public int columnSqlType;
0318: //public String columnSqlTypeName;
0319: public String toString() {
0320: if (tableName != null && tableName.length() > 0) {
0321: return tableName + DOT + columnName;
0322: } else {
0323: return columnName;
0324: }
0325: }
0326:
0327: public String getValueRef() {
0328: return JSFEL_START + varName + JSFEL_OPENQUOT + columnName
0329: + JSFEL_CLOSEQUOT + JSFEL_END;
0330: }
0331: }
0332:
0333: public class PagingInfo {
0334: //public boolean paging;
0335: public int rows;
0336:
0337: public String navigation = BUTTON_NONE;
0338: public boolean navOnTop;
0339: public boolean navOnBottom;
0340: public String align = ALIGN_CENTER;
0341:
0342: public boolean firstButton;
0343: public String firstButtonText = DEFAULT_FIRST_TEXT;
0344: public String firstButtonUrl = DEFAULT_FIRST_URL;
0345: public boolean previousButton;
0346: public String previousButtonText = DEFAULT_PREVIOUS_TEXT;
0347: public String previousButtonUrl = DEFAULT_PREVIOUS_URL;
0348: public boolean nextButton;
0349: public String nextButtonText = DEFAULT_NEXT_TEXT;
0350: public String nextButtonUrl = DEFAULT_NEXT_URL;
0351: public boolean lastButton;
0352: public String lastButtonText = DEFAULT_LAST_TEXT;
0353: public String lastButtonUrl = DEFAULT_LAST_URL;
0354: }
0355:
0356: public class DisplayInfo {
0357: private static final int MAX_DISPLAY_COLUMNS = 9999;
0358: private List displayColumnList = new ArrayList();
0359: private DisplayColumn[] savedColumns;
0360:
0361: public void addColumn(ResultSetColumn rsc) {
0362: DisplayColumn dc = new DisplayColumn();
0363: //let dc.columnInstanceName be null
0364: dc.compClassName = HtmlOutputText.class.getName();
0365: dc.compValueRef = rsc.getValueRef();
0366: dc.headerText = rsc.columnName;
0367: //let dc.footerText be null
0368: dc.itemText = rsc.toString();
0369: dc.hasResultSetColumnPeer = true;
0370: addColumn(dc);
0371: }
0372:
0373: public DisplayColumn addNewColumn() {
0374: DisplayColumn dc = new DisplayColumn();
0375: List names = new ArrayList();
0376: for (int i = 0; i < displayColumnList.size(); i++) {
0377: String aColumnInstanceName = ((DisplayColumn) displayColumnList
0378: .get(i)).columnInstanceName;
0379: if (aColumnInstanceName != null) {
0380: names.add(aColumnInstanceName);
0381: }
0382: }
0383: for (int i = 1; i < MAX_DISPLAY_COLUMNS; i++) {
0384: if (!names.contains(COLUMN_ITEM_TEXT + i)) {
0385: dc.columnInstanceName = COLUMN_ITEM_TEXT + i;
0386: break;
0387: }
0388: }
0389: dc.compClassName = HtmlOutputText.class.getName();
0390: //let dc.compValueRef be null
0391: dc.headerText = dc.columnInstanceName;
0392: //let dc.footerText be null
0393: dc.itemText = dc.columnInstanceName;
0394: addColumn(dc);
0395: return dc;
0396: }
0397:
0398: public DisplayColumn[] getColumns() {
0399: return (DisplayColumn[]) displayColumnList
0400: .toArray(new DisplayColumn[displayColumnList.size()]);
0401: }
0402:
0403: public void addColumn(DisplayColumn dc) {
0404: displayColumnList.add(dc);
0405: }
0406:
0407: public void removeColumn(DisplayColumn dc) {
0408: displayColumnList.remove(dc);
0409: }
0410:
0411: public void clearColumns() {
0412: displayColumnList.clear();
0413: }
0414:
0415: public int getColumnCount() {
0416: return displayColumnList.size();
0417: }
0418:
0419: public DisplayColumn getColumn(int index) {
0420: return (DisplayColumn) displayColumnList.get(index);
0421: }
0422:
0423: public boolean canMoveUp(DisplayColumn dc) {
0424: return displayColumnList.indexOf(dc) > 0;
0425: }
0426:
0427: public void moveColumnUp(DisplayColumn dc) {
0428: int idx = displayColumnList.indexOf(dc);
0429: if (idx > 0) {
0430: displayColumnList.remove(dc);
0431: displayColumnList.add(idx - 1, dc);
0432: }
0433: }
0434:
0435: public boolean canMoveDown(DisplayColumn dc) {
0436: int idx = displayColumnList.indexOf(dc);
0437: return idx > -1 && idx < displayColumnList.size() - 1;
0438: }
0439:
0440: public void moveColumnDown(DisplayColumn dc) {
0441: int idx = displayColumnList.indexOf(dc);
0442: if (idx > -1 && idx < displayColumnList.size() - 1) {
0443: displayColumnList.remove(dc);
0444: displayColumnList.add(idx + 1, dc);
0445: }
0446: }
0447:
0448: private void saveDisplayColumns() {
0449: savedColumns = getColumns();
0450: }
0451: }
0452:
0453: public class DisplayColumn {
0454: public DesignBean columnDesignBean; //live bean holding a UIColumn object
0455: public String columnInstanceName; //instance name of UIColumn in source code, like column1.
0456: //public String compInstanceName; //the field component instance's instance name in source code, like outputText2 (instance of type HtmlOutputText)
0457: public String compClassName; //like javax.faces.component.html.HtmlOutputText or other UIComponent subclass. used to create a DesignBean to wrap the component
0458: public String compValueRef; //like #{currentRow['PERSONID']} or #{currentRow.donkey}
0459: public String compSIValueRef; //if comp class is HtmlSelectOneMenu, then the value attribute of its select items is this jsf-el expression
0460: public String headerText;
0461: //public boolean headerLink; //whether header text is an hypertext link to sort that column
0462: public String footerText;
0463: public String itemText; //what gets displayed in the list
0464: public boolean hasResultSetColumnPeer;
0465:
0466: public String toString() {
0467: return itemText;
0468: }
0469: }
0470:
0471: private String getStrippedJsfEL(String valueRef) {
0472: if (valueRef == null) {
0473: return null;
0474: }
0475: if (!valueRef.startsWith(JSFEL_START)
0476: || !valueRef.endsWith(JSFEL_END)) {
0477: return valueRef;
0478: }
0479: return valueRef.substring(JSFEL_START.length(), valueRef
0480: .indexOf(JSFEL_END));
0481: }
0482:
0483: private String getTextFromDesignProperty(DesignProperty vp) {
0484: return vp == null ? null : vp.getValueSource();
0485: }
0486:
0487: boolean isJsfELSyntax(String s) {
0488: if (s == null) {
0489: return false;
0490: }
0491: return s.startsWith(JSFEL_START) && s.endsWith(JSFEL_END);
0492: }
0493:
0494: boolean validateJsfEL(String s) {
0495: //right now it makes sense for the dialog to relax its restrictions, since QE has found cases where
0496: //this strategy is prohibitively restrictive, i.e., it returns false though the expression would work at runtime.
0497: //for instance, see 6183023
0498: FacesDesignContext flc = (FacesDesignContext) tableBean
0499: .getDesignContext();
0500: FacesContext facesContext = flc.getFacesContext();
0501: Application facesApp = facesContext.getApplication();
0502: try {
0503: ValueBinding vb = facesApp.createValueBinding(s);
0504: Object result = vb.getValue(facesContext);
0505: return true;
0506: } catch (ReferenceSyntaxException rse) {
0507: return false;
0508: }
0509: /*
0510: //tableBean.getDesignContext() must be an instance of FacesDesignContext. otherwise it makes no sense to call this method.
0511: if (!isJsfELSyntax(s)) {
0512: return false;
0513: }
0514:
0515: if (!(tableBean.getDesignContext() instanceof FacesDesignContext)) {
0516: return false;
0517: }
0518: FacesDesignContext flc = (FacesDesignContext)tableBean.getDesignContext();
0519: FacesContext facesContext = flc.getFacesContext();
0520: Application facesApp = facesContext.getApplication();
0521: //if sourceInstance is a ResultSet and is relative to varName, then we know the absolute expression and can use it for more stringent validation
0522: if (getSourceInstance() instanceof ResultSet && s.startsWith(JSFEL_START + varName)) {
0523: DesignContext sbContext = sourceBean.getDesignContext();
0524: s = JSFEL_START + ((FacesDesignContext)sbContext).getReferenceName() + DOT +
0525: sourceBean.getInstanceName() + DOT + getStrippedJsfEL(s) + JSFEL_END;
0526: }
0527: try {
0528: ValueBinding vb = facesApp.createValueBinding(s);
0529: Object result = vb.getValue(facesContext);
0530: return true;
0531: } catch (EvaluationException ee) {
0532: return false;
0533: }
0534: */
0535: }
0536:
0537: private DesignEvent getActionEvent(DesignBean commandBean) {
0538: DesignEvent[] events = commandBean.getEvents();
0539: for (int e = 0; e < events.length; e++) {
0540: if (ACTION_LIVE_EVENT.equals(events[e].getEventDescriptor()
0541: .getName())) {
0542: return events[e];
0543: }
0544: }
0545: return null;
0546: }
0547:
0548: private DesignBean[] getPagingComponents(DesignBean panel) {
0549: //facet can be null
0550: DesignBean[] pagingComponents = new DesignBean[PAGING_HANDLER_SUFFIXES.length]; //a place to put the paging buttons or links for the panel
0551: if (panel == null) {
0552: return pagingComponents;
0553: }
0554: Object panelInstance = panel.getInstance();
0555: if (!(panelInstance instanceof HtmlPanelGrid || panelInstance instanceof HtmlPanelGroup)) {
0556: return pagingComponents;
0557: }
0558: boolean panelContainsPagingComponents = false;
0559: DesignBean[] children = panel.getChildBeans();
0560: childrenLoop: for (int i = 0; i < children.length; i++) { //go through the components within the panel
0561:
0562: if (!(children[i].getInstance() instanceof UICommand)) {
0563: continue; //if this component is not a button or link, go to the next component
0564: }
0565: DesignEvent actionEvent = getActionEvent(children[i]); //get the action event associated with this component
0566: if (actionEvent == null) {
0567: continue; //go to the next component
0568: }
0569: String actionEventHandler = actionEvent.getHandlerName(); //the handler method name for the action event
0570: if (actionEventHandler == null) {
0571: continue; //go to the next component
0572: }
0573: for (int j = 0; j < PAGING_HANDLER_SUFFIXES.length; j++) {
0574: //if we already have a component for this paging handler suffix, go to the next suffix
0575: if (pagingComponents[j] != null) {
0576: continue;
0577: }
0578: if (actionEventHandler.equals(tableBean
0579: .getInstanceName()
0580: + PAGING_HANDLER_SUFFIXES[j])) {
0581: //children[i]'s action handler method is the paging handler for this suffix
0582: pagingComponents[j] = children[i];
0583: panelContainsPagingComponents = true;
0584: continue childrenLoop;
0585: }
0586: }
0587: }
0588: if (panelContainsPagingComponents) {
0589: if (panelInstance instanceof HtmlPanelGroup) {
0590: DesignProperty panelStyleProp = panel
0591: .getProperty("style"); //NOI18N
0592: if (panelStyleProp != null) {
0593: String panelStyle = panelStyleProp.getValueSource();
0594: if (panelStyle != null) {
0595: String patternPrefix = ".*?text-align\\s*:\\s*"; //NOI18N
0596: if (panelStyle.matches(patternPrefix + "left" //NOI18N
0597: )) {
0598: paging.align = ALIGN_LEFT;
0599: } else if (panelStyle.matches(patternPrefix
0600: + "center" //NOI18N
0601: )) {
0602: paging.align = ALIGN_CENTER;
0603: } else if (panelStyle.matches(patternPrefix
0604: + "right" //NOI18N
0605: )) {
0606: paging.align = ALIGN_RIGHT;
0607: }
0608: }
0609: }
0610: }
0611: }
0612: return pagingComponents;
0613: }
0614:
0615: private void setBasicPagingVariables(DesignBean[] pagingComponents,
0616: String facetStr) {
0617: //find out if there's at least one paging component for this facet. pagingComponents should not be null.
0618: boolean atLeastOne = false;
0619: for (int j = 0; j < pagingComponents.length; j++) {
0620: if (pagingComponents[j] != null) {
0621: atLeastOne = true;
0622: break;
0623: }
0624: }
0625: //set paging variables
0626: if (atLeastOne) {
0627: if ("header".equals(facetStr)) { //NOI18N
0628: paging.navOnTop = true;
0629: } else {
0630: paging.navOnBottom = true;
0631: }
0632: }
0633: }
0634:
0635: ////////////////////////////////////////////////////////////////////////////////////////////////
0636:
0637: public void loadState() {
0638: try {
0639: ////set instance vars
0640: //instanceName = tableBean.getInstanceName();
0641: Object sourceInst = tableBean.getProperty("value")
0642: .getValue(); //NOI18N
0643: if (sourceInst instanceof CachedRowSetDataModel) {
0644: sourceInst = ((CachedRowSetDataModel) sourceInst)
0645: .getWrappedData();
0646: }
0647: sourceBean = getDesignBeanForSourceInstance(sourceInst); //do not call setSourceBean(...) here! use sourceBean = ...!
0648: savedSourceBean = sourceBean;
0649: varName = tableBean.getProperty("var").getValueSource(); //NOI18N
0650: if (varName == null || varName.length() == 0) {
0651: varName = DEFAULT_VAR_NAME;
0652:
0653: //paging stuff
0654: }
0655: Object pagingRows = tableBean.getProperty("rows")
0656: .getValue(); //NOI18N
0657: if (pagingRows != null) {
0658: paging.rows = ((Integer) pagingRows).intValue(); //number of rows per "page" if paging is enabled on this table
0659: }
0660: if (tableBean instanceof FacesDesignBean) {
0661: paging.align = ALIGN_CENTER;
0662: paging.navOnTop = false;
0663: paging.navOnBottom = false;
0664: FacesDesignBean ftableBean = (FacesDesignBean) tableBean;
0665: DesignBean header = ftableBean.getFacet("header"); //can be null //NOI18N
0666: DesignBean footer = ftableBean.getFacet("footer"); //can be null //NOI18N
0667: DesignBean[] headerPagingComponents = getPagingComponents(header); //won't be null
0668: setBasicPagingVariables(headerPagingComponents,
0669: "header"); //NOI18N
0670: DesignBean[] footerPagingComponents = getPagingComponents(footer); //won't be null
0671: setBasicPagingVariables(footerPagingComponents,
0672: "footer"); //NOI18N
0673:
0674: //merge the header and footer paging component arrays
0675: DesignBean[] mergedPagingComponents = headerPagingComponents;
0676: headerPagingComponents = null;
0677: for (int i = 0; i < footerPagingComponents.length; i++) {
0678: if (footerPagingComponents[i] != null) {
0679: mergedPagingComponents[i] = footerPagingComponents[i];
0680: }
0681: }
0682: footerPagingComponents = null;
0683:
0684: /*
0685: System.err.println("HtmlDataTableState.loadState: mergedPagingComponents:"); //NOI18N
0686: for (int m = 0; m < mergedPagingComponents.length; m++) {
0687: System.err.println("\t" + m + ":" + mergedPagingComponents[m] + "!"); //NOI18N
0688: }
0689: */
0690:
0691: paging.navigation = BUTTON_NONE;
0692: if (mergedPagingComponents[0] != null) {
0693: paging.firstButton = true;
0694: //we have a button. upgrade to BUTTON_TEXT.
0695: paging.navigation = BUTTON_TEXT;
0696: String buttonText = (String) mergedPagingComponents[0]
0697: .getProperty("value").getValueSource(); //NOI18N
0698: paging.firstButtonText = buttonText == null
0699: || buttonText.length() < 1 ? DEFAULT_FIRST_TEXT
0700: : buttonText;
0701: String buttonImageUrl = (String) mergedPagingComponents[0]
0702: .getProperty("image").getValueSource(); //NOI18N
0703: boolean buttonImageUrlEmpty = buttonImageUrl == null
0704: || buttonImageUrl.length() < 1;
0705: paging.firstButtonUrl = buttonImageUrlEmpty ? DEFAULT_FIRST_URL
0706: : buttonImageUrl;
0707: if (!buttonImageUrlEmpty) {
0708: paging.navigation = BUTTON_IMAGE;
0709: }
0710: } else {
0711: paging.firstButton = false;
0712: }
0713: if (mergedPagingComponents[1] != null) {
0714: paging.previousButton = true;
0715: //we have a button. so if paging.navigation was BUTTON_NONE, upgrade to BUTTON_TEXT.
0716: if (BUTTON_NONE.equals(paging.navigation)) {
0717: paging.navigation = BUTTON_TEXT;
0718: }
0719: String buttonText = (String) mergedPagingComponents[1]
0720: .getProperty("value").getValueSource(); //NOI18N
0721: paging.previousButtonText = buttonText == null
0722: || buttonText.length() < 1 ? DEFAULT_PREVIOUS_TEXT
0723: : buttonText;
0724: String buttonImageUrl = (String) mergedPagingComponents[1]
0725: .getProperty("image").getValueSource(); //NOI18N
0726: boolean buttonImageUrlEmpty = buttonImageUrl == null
0727: || buttonImageUrl.length() < 1;
0728: paging.previousButtonUrl = buttonImageUrlEmpty ? DEFAULT_PREVIOUS_URL
0729: : buttonImageUrl;
0730: if (!buttonImageUrlEmpty) {
0731: paging.navigation = BUTTON_IMAGE;
0732: }
0733: } else {
0734: paging.previousButton = false;
0735: }
0736: if (mergedPagingComponents[2] != null) {
0737: paging.nextButton = true;
0738: if (BUTTON_NONE.equals(paging.navigation)) {
0739: paging.navigation = BUTTON_TEXT;
0740: }
0741: String buttonText = (String) mergedPagingComponents[2]
0742: .getProperty("value").getValueSource(); //NOI18N
0743: paging.nextButtonText = buttonText == null
0744: || buttonText.length() < 1 ? DEFAULT_NEXT_TEXT
0745: : buttonText;
0746: String buttonImageUrl = (String) mergedPagingComponents[2]
0747: .getProperty("image").getValueSource(); //NOI18N
0748: boolean buttonImageUrlEmpty = buttonImageUrl == null
0749: || buttonImageUrl.length() < 1;
0750: paging.nextButtonUrl = buttonImageUrlEmpty ? DEFAULT_NEXT_URL
0751: : buttonImageUrl;
0752: if (!buttonImageUrlEmpty) {
0753: paging.navigation = BUTTON_IMAGE;
0754: }
0755: } else {
0756: paging.nextButton = false;
0757: }
0758: if (mergedPagingComponents[3] != null) {
0759: paging.lastButton = true;
0760: if (BUTTON_NONE.equals(paging.navigation)) {
0761: paging.navigation = BUTTON_TEXT;
0762: }
0763: String buttonText = (String) mergedPagingComponents[3]
0764: .getProperty("value").getValueSource(); //NOI18N
0765: paging.lastButtonText = buttonText == null
0766: || buttonText.length() < 1 ? DEFAULT_LAST_TEXT
0767: : buttonText;
0768: String buttonImageUrl = (String) mergedPagingComponents[3]
0769: .getProperty("image").getValueSource(); //NOI18N
0770: boolean buttonImageUrlEmpty = buttonImageUrl == null
0771: || buttonImageUrl.length() < 1;
0772: paging.lastButtonUrl = buttonImageUrlEmpty ? DEFAULT_LAST_URL
0773: : buttonImageUrl;
0774: if (!buttonImageUrlEmpty) {
0775: paging.navigation = BUTTON_IMAGE;
0776: }
0777: } else {
0778: paging.lastButton = false;
0779: }
0780: }
0781: loadColumnState();
0782: } catch (Exception x) {
0783: System.err
0784: .println("error in HtmlDataTableState.loadState():"); //NOI18N
0785: x.printStackTrace();
0786: //System.err.println("dumping state of HtmlDataTableState:"); //NOI18N
0787: //dumpState(System.err);
0788: }
0789: }
0790:
0791: void loadColumnState() {
0792: try {
0793: Object sourceInst = getSourceInstance();
0794:
0795: //update rsinfo if applicable
0796: if (sourceInst instanceof ResultSet) {
0797: if (rsinfo == null) {
0798: rsinfo = new ResultSetInfo();
0799: }
0800: rsinfo.refreshColumns();
0801: } else {
0802: rsinfo = null;
0803: }
0804:
0805: //update display instance variable
0806: display.clearColumns();
0807: DesignBean[] uicolumns = tableBean.getChildBeans();
0808: for (int i = 0; uicolumns != null && i < uicolumns.length; i++) {
0809: if (!(uicolumns[i].getInstance() instanceof UIColumn)) {
0810: continue;
0811: }
0812: DisplayColumn dc = new DisplayColumn();
0813: dc.columnDesignBean = uicolumns[i];
0814: dc.columnInstanceName = uicolumns[i].getInstanceName();
0815: DesignBean[] comps = uicolumns[i].getChildBeans();
0816:
0817: DesignBean header = null;
0818: DesignBean footer = null;
0819:
0820: // get the header and footer text from the facets
0821: if (uicolumns[i] instanceof FacesDesignBean) {
0822: FacesDesignBean flb = (FacesDesignBean) uicolumns[i];
0823: header = flb.getFacet("header"); //NOI18N
0824: if (header != null
0825: && header.getInstance() instanceof HtmlOutputText) {
0826: DesignProperty vp = header.getProperty("value"); //NOI18N
0827: dc.headerText = getTextFromDesignProperty(vp);
0828: }
0829: footer = flb.getFacet("footer"); //NOI18N
0830: if (footer != null
0831: && footer.getInstance() instanceof HtmlOutputText) {
0832: DesignProperty vp = footer.getProperty("value"); //NOI18N
0833: dc.footerText = getTextFromDesignProperty(vp);
0834: }
0835: }
0836:
0837: if (comps != null && comps.length >= 1) {
0838: DesignBean comp = null;
0839: for (int c = 0; c < comps.length; c++) {
0840: if (comps[c] != null && comps[c] != header
0841: && comps[c] != footer) {
0842: comp = comps[c];
0843: break;
0844: }
0845: }
0846: if (comp != null) {
0847: //dc.compInstanceName = comp.getInstanceName();
0848: dc.compClassName = comp.getInstance()
0849: .getClass().getName();
0850: DesignProperty valProp = comp
0851: .getProperty("value"); //NOI18N
0852: dc.compValueRef = valProp != null ? valProp
0853: .getValueSource() : null; //NOI18N
0854: if (dc.compClassName
0855: .equals(HtmlSelectOneMenu.class
0856: .getName())
0857: || dc.compClassName
0858: .equals(HtmlSelectOneRadio.class
0859: .getName())) {
0860: DesignBean[] compChildren = comp
0861: .getChildBeans();
0862: if (compChildren != null
0863: && compChildren.length > 0) {
0864: if (compChildren[0] != null
0865: && (compChildren[0]
0866: .getInstance() instanceof UISelectItems)) {
0867: DesignProperty siValueProp = compChildren[0]
0868: .getProperty("value"); //NOI18N
0869: if (siValueProp != null) {
0870: dc.compSIValueRef = siValueProp
0871: .getValueSource();
0872: }
0873: }
0874: }
0875: } else if (dc.compClassName
0876: .equals(HtmlCommandLink.class.getName())) {
0877: DesignBean[] compChildren = comp
0878: .getChildBeans();
0879: if (compChildren != null
0880: && compChildren.length > 0) {
0881: if (compChildren[0] != null
0882: && (compChildren[0]
0883: .getInstance() instanceof HtmlOutputText)) {
0884: DesignProperty childValueProp = compChildren[0]
0885: .getProperty("value"); //NOI18N
0886: if (childValueProp != null) {
0887: dc.compValueRef = childValueProp
0888: .getValueSource();
0889: }
0890: }
0891: }
0892: }
0893: }
0894: }
0895:
0896: //set dc.itemText
0897: if (sourceInst instanceof ResultSet
0898: && dc.compValueRef != null) {
0899: ResultSetColumn[] rsca = rsinfo.getColumns();
0900: for (int j = 0; j < rsca.length; j++) {
0901: if (dc.compValueRef.equals(rsca[j]
0902: .getValueRef())) {
0903: dc.itemText = rsca[j].toString();
0904: dc.hasResultSetColumnPeer = true;
0905: break;
0906: }
0907: }
0908: }
0909: if (dc.itemText == null) {
0910: dc.itemText = dc.columnInstanceName;
0911: }
0912:
0913: display.addColumn(dc);
0914: }
0915:
0916: display.saveDisplayColumns();
0917: } catch (Exception x) {
0918: System.err
0919: .println("error in HtmlDataTableState.loadColumnState():"); //NOI18N
0920: x.printStackTrace();
0921: //System.err.println("dumping state of HtmlDataTableState:"); //NOI18N
0922: //dumpState(System.err);
0923: }
0924: }
0925:
0926: protected boolean dontSaveModelValueExpr = false;
0927: protected String modelValueExpr = null;
0928:
0929: public String saveStateExceptModelValueExpr() {
0930: this .dontSaveModelValueExpr = true;
0931: saveState();
0932: this .dontSaveModelValueExpr = false;
0933: return this .modelValueExpr;
0934: }
0935:
0936: public void saveState() {
0937: //System.err.println("in HtmlDataTableState.saveState(): dumping state of HtmlDataTableState:"); //NOI18N
0938: //dumpState(System.err);
0939:
0940: DesignContext context = tableBean.getDesignContext();
0941: String outer = ((FacesDesignContext) context)
0942: .getReferenceName();
0943: FacesDesignContext flc = null;
0944: if (context instanceof FacesDesignContext) {
0945: flc = (FacesDesignContext) context;
0946: }
0947:
0948: DisplayColumn[] dca = display.getColumns();
0949:
0950: /*
0951: //copy over columnDesignBean from savedColumns to corresponding display columns as needed
0952: if (sourceBean == savedSourceBean && getSourceInstance() instanceof ResultSet) {
0953: for (int d = 0; d < dca.length; d++) {
0954: DisplayColumn dc = dca[d];
0955: if (dc == null || dc.columnDesignBean != null || dc.compValueRef == null) continue;
0956: DisplayColumn[] sca = display.savedColumns;
0957: for (int s = 0; s < sca.length; s++) {
0958: DisplayColumn sc = sca[s];
0959: if (sc == null) continue; //just defensive
0960: if (dc.compValueRef.equals(sc.compValueRef)) {
0961: dc.columnDesignBean = sc.columnDesignBean;
0962: }
0963: }
0964: }
0965: }
0966: */
0967:
0968: //nuke just the deleted columns (kids)
0969: DesignBean[] kids = tableBean.getChildBeans();
0970: for (int k = 0; kids != null && k < kids.length; k++) {
0971: DesignBean kid = kids[k];
0972: if (kid == null) {
0973: continue;
0974: }
0975: boolean keep = false;
0976: //go through display columns. keep this kid if we need it.
0977: for (int d = 0; d < dca.length; d++) {
0978: DisplayColumn dc = dca[d];
0979: if (kid == dc.columnDesignBean) {
0980: keep = true;
0981: break;
0982: }
0983: }
0984: if (!keep) {
0985: context.deleteBean(kid);
0986: }
0987: }
0988:
0989: /*
0990: * also nuke the facets. Note: This will irretrievably nuke any components the user has hand-coded in the facets!
0991: * the alternative is to make getPagingComponents return something that holds more than 4 buttons/links.
0992: * (For instance, there might be 10 buttons in the facet with 3 of them having the action event handler method dataTable1_previousPageAction.)
0993: * and then only nuke the *paging* components in the facet and then the whole facet only if there are no components left
0994: */
0995: if (tableBean instanceof FacesDesignBean) {
0996: DesignBean facet = ((FacesDesignBean) tableBean)
0997: .getFacet("header"); //NOI18N
0998: if (facet != null) {
0999: context.deleteBean(facet);
1000: }
1001: facet = ((FacesDesignBean) tableBean).getFacet("footer"); //NOI18N
1002: if (facet != null) {
1003: context.deleteBean(facet);
1004: //System.err.println("HtmlDataTableState.saveState: header exists?: " + ((FacesDesignBean)tableBean).getFacet("header")); //NOI18N
1005: //System.err.println("HtmlDataTableState.saveState: footer exists?: " + ((FacesDesignBean)tableBean).getFacet("footer")); //NOI18N
1006: }
1007: }
1008:
1009: // now create new children...
1010: for (int i = 0; i < dca.length; i++) {
1011: DisplayColumn dc = dca[i];
1012: DesignBean uicolumn = dc.columnDesignBean;
1013: if (uicolumn == null) {
1014: uicolumn = context.createBean(UIColumn.class.getName(),
1015: tableBean, new Position(i));
1016: uicolumn.setInstanceName(dc.columnInstanceName, true);
1017: } else {
1018: context.moveBean(uicolumn, tableBean, new Position(i));
1019: }
1020:
1021: DesignBean comp = null;
1022: DesignBean header = null;
1023: DesignBean footer = null;
1024:
1025: if (uicolumn instanceof FacesDesignBean) {
1026: FacesDesignBean fuicolumn = (FacesDesignBean) uicolumn;
1027: header = fuicolumn.getFacet("header"); //NOI18N
1028: footer = fuicolumn.getFacet("footer"); //NOI18N
1029: }
1030:
1031: DesignBean[] comps = uicolumn.getChildBeans();
1032: for (int c = 0; comps != null && c < comps.length; c++) {
1033: if (comps[c] != null && comps[c] != header
1034: && comps[c] != footer) {
1035: comp = comps[c];
1036: break;
1037: }
1038: }
1039:
1040: // if we have a first comp of the wrong type, wipe it out
1041: if (comp != null) {
1042: Object compInstance = comp.getInstance();
1043: if (compInstance == null
1044: || !compInstance.getClass().getName().equals(
1045: dc.compClassName)) {
1046: //first comp of wrong type. wipe it out.
1047: context.deleteBean(comp);
1048: comp = null;
1049: }
1050: }
1051:
1052: if (comp == null) {
1053: if (dc.compClassName == null) {
1054: dc.compClassName = HtmlOutputText.class.getName();
1055: }
1056: comp = context.createBean(dc.compClassName, uicolumn,
1057: new Position(0));
1058: if (dc.compClassName.equals(HtmlSelectOneMenu.class
1059: .getName())
1060: || dc.compClassName
1061: .equals(HtmlSelectOneRadio.class
1062: .getName())) {
1063: DesignBean selectitems = context.createBean(
1064: UISelectItems.class.getName(), comp, null);
1065: selectitems.setInstanceName(comp.getInstanceName()
1066: + "SelectItems", true); //NOI18N
1067: DesignBean items = context.createBean(
1068: DefaultSelectItemsArray.class.getName(),
1069: null, null);
1070: items.setInstanceName(comp.getInstanceName()
1071: + "DefaultItems", true); //NOI18N
1072: selectitems
1073: .getProperty("value")
1074: .setValueSource(JSFEL_START + outer + DOT + //NOI18N
1075: items.getInstanceName() + JSFEL_END); //NOI18N
1076: } else if (dc.compClassName
1077: .equals(HtmlCommandLink.class.getName())) {
1078: DesignBean childText = comp.getDesignContext()
1079: .createBean(HtmlOutputText.class.getName(),
1080: comp, null);
1081: childText.setInstanceName(comp.getInstanceName()
1082: + "Text", true); //NOI18N
1083: } else if (dc.compClassName.equals(HtmlMessage.class
1084: .getName())) {
1085: comp.getProperty("for").setValue(""); //NOI18N
1086: comp.getProperty("showDetail").setValue(
1087: Boolean.FALSE); //NOI18N
1088: comp.getProperty("showSummary").setValue(
1089: Boolean.TRUE); //NOI18N
1090: comp.getProperty("infoClass").setValue(
1091: "infoMessage"); // NOI18N
1092: comp.getProperty("warnClass").setValue(
1093: "warnMessage"); // NOI18N
1094: comp.getProperty("errorClass").setValue(
1095: "errorMessage"); // NOI18N
1096: comp.getProperty("fatalClass").setValue(
1097: "fatalMessage"); // NOI18N
1098: }
1099: }
1100:
1101: DesignProperty valProp = comp.getProperty("value"); //NOI18N
1102: if (dc.compClassName
1103: .equals(HtmlCommandLink.class.getName())) {
1104: if (valProp != null) {
1105: valProp.unset();
1106: }
1107: DesignBean childText = null; //the HtmlOutputText child of the link action, if it exists
1108: DesignBean[] compChildren = comp.getChildBeans();
1109: if (compChildren != null && compChildren.length > 0) {
1110: if (compChildren[0] != null
1111: && (compChildren[0].getInstance() instanceof HtmlOutputText)) {
1112: childText = compChildren[0];
1113: }
1114: }
1115: if (childText != null) {
1116: String childTextValue = bundle
1117: .getMessage("linkAction"); //NOI18N
1118: if (dc.compValueRef != null) {
1119: childTextValue = dc.compValueRef;
1120: }
1121: if (isJsfELSyntax(childTextValue)) {
1122: childText.getProperty("value").setValueSource(
1123: childTextValue); //NOI18N
1124: } else {
1125: childText.getProperty("value").setValue(
1126: childTextValue); //NOI18N
1127: }
1128: }
1129: } else if (dc.compValueRef == null
1130: || dc.compValueRef.length() == 0) {
1131: if (valProp != null) {
1132: valProp.unset();
1133: }
1134: } else {
1135: if (valProp != null) {
1136: if (isJsfELSyntax(dc.compValueRef)) {
1137: valProp.setValueSource(dc.compValueRef); //NOI18N
1138: } else {
1139: valProp.setValue(dc.compValueRef);
1140: }
1141: }
1142: }
1143:
1144: // setup the header and footer facets
1145: if (header == null && dc.headerText != null && flc != null) {
1146: if (flc.canCreateFacet("header", HtmlOutputText.class
1147: .getName(), uicolumn)) { //NOI18N
1148: header = flc.createFacet("header",
1149: HtmlOutputText.class.getName(), uicolumn); //NOI18N
1150: }
1151: }
1152: if (header != null) {
1153: DesignProperty vp = header.getProperty("value"); //NOI18N
1154: if (vp != null) {
1155: if (isJsfELSyntax(dc.headerText)) {
1156: vp.setValueSource(dc.headerText);
1157: } else {
1158: vp.setValue(dc.headerText);
1159: }
1160: }
1161: }
1162: if (footer == null && dc.footerText != null && flc != null) {
1163: if (flc.canCreateFacet("footer", HtmlOutputText.class
1164: .getName(), uicolumn)) { //NOI18N
1165: footer = flc.createFacet("footer",
1166: HtmlOutputText.class.getName(), uicolumn); //NOI18N
1167: }
1168: }
1169: if (footer != null) {
1170: DesignProperty vp = footer.getProperty("value"); //NOI18N
1171: if (vp != null) {
1172: if (isJsfELSyntax(dc.footerText)) {
1173: vp.setValueSource(dc.footerText);
1174: } else {
1175: vp.setValue(dc.footerText);
1176: }
1177: }
1178: }
1179: }
1180:
1181: // If the source instance is a RowSet ...
1182: DesignBean dm = null;
1183: if (sourceBean != null) {
1184: Object sourceInst = sourceBean.getInstance();
1185: if (sourceInst instanceof RowSet) {
1186:
1187: // Create or replace the corresponding datamodel
1188: DesignContext lc = tableBean.getDesignContext();
1189: String dmName = tableBean.getInstanceName() + "Model"; //NOI18N
1190: dm = lc.getBeanByName(dmName);
1191: if (dm != null) {
1192: dm.getDesignContext().deleteBean(dm);
1193: }
1194: dm = lc.createBean(CachedRowSetDataModel.class
1195: .getName(), null, null);
1196: dm.setInstanceName(dmName);
1197:
1198: // Configure properties on the new datamodel
1199: dm.getProperty("cachedRowSet").setValue(
1200: sourceBean.getInstance()); // NOI18N
1201:
1202: }
1203: }
1204:
1205: //now properties
1206: //System.err.println("HtmlTableDataState.saveState: getStrippedSourceBeanValueRef():" + getStrippedSourceBeanValueRef() + "!"); //NOI18N
1207: if (sourceBean == null) { // No value binding at all
1208: if (dontSaveModelValueExpr) {
1209: this .modelValueExpr = null;
1210: } else {
1211: tableBean.getProperty("value").unset(); //NOI18N
1212: }
1213: } else if (dm != null) { // Bound to a RowSet
1214: if (dontSaveModelValueExpr) {
1215: DesignContext dmc = dm.getDesignContext();
1216: if (dmc instanceof FacesDesignContext) {
1217: this .modelValueExpr = JSFEL_START
1218: + ((FacesDesignContext) dmc)
1219: .getReferenceName() + DOT
1220: + dm.getInstanceName() + JSFEL_END;
1221: } else {
1222: this .modelValueExpr = JSFEL_START
1223: + dmc.getDisplayName() + DOT
1224: + dm.getInstanceName() + JSFEL_END;
1225: }
1226: } else {
1227: tableBean.getProperty("value").setValue(
1228: dm.getInstance()); // NOI18N
1229: }
1230: } else { // Bound to something else
1231: String vref = JSFEL_START + getStrippedSourceBeanValueRef()
1232: + JSFEL_END;
1233: if (dontSaveModelValueExpr) {
1234: this .modelValueExpr = vref;
1235: } else {
1236: if (isJsfELSyntax(vref)) {
1237: tableBean.getProperty("value").setValueSource(vref); //NOI18N
1238: } else {
1239: tableBean.getProperty("value").setValue(vref); //NOI18N
1240: }
1241: }
1242: }
1243: savedSourceBean = sourceBean;
1244: display.saveDisplayColumns();
1245: tableBean.getProperty("var").setValue(varName); //NOI18N
1246: try {
1247: tableBean.getProperty("rows").setValue(
1248: new Integer(paging.rows)); //NOI18N
1249: } catch (Exception x) {
1250: }
1251:
1252: //now navigation buttons
1253: boolean atLeastOneButtonRequested = paging.firstButton
1254: || paging.previousButton || paging.nextButton
1255: || paging.lastButton;
1256: if (paging.rows > 0
1257: && (BUTTON_TEXT.equals(paging.navigation) || BUTTON_IMAGE
1258: .equals(paging.navigation))
1259: && atLeastOneButtonRequested) {
1260: if (paging.navOnTop) {
1261: createNavPanel("header"); //NOI18N
1262: }
1263: if (paging.navOnBottom) {
1264: createNavPanel("footer"); //NOI18N
1265: }
1266: }
1267: }
1268:
1269: /**
1270: * Create a facet as a DesignBean as well as all buttons within the facet and set the buttons' action event handler method name and source code. Called by saveState.
1271: */
1272: private void createNavPanel(String facetStr) {
1273: DesignContext context = tableBean.getDesignContext();
1274: FacesDesignContext flc = null;
1275: if (context instanceof FacesDesignContext) {
1276: flc = (FacesDesignContext) context;
1277: }
1278: if (!flc.canCreateFacet(facetStr,
1279: HtmlPanelGrid.class.getName(), tableBean)) {
1280: System.err
1281: .println("HtmlTableDataState.createNavPanel: error: could not create facet of type "
1282: + //NOI18N
1283: facetStr + " for tableBean " + tableBean); //NOI18N
1284: return;
1285: }
1286:
1287: //create a facet
1288: DesignBean facet = flc.createFacet(facetStr,
1289: HtmlPanelGroup.class.getName(), tableBean);
1290:
1291: //give it a style
1292: DesignProperty facetProp = facet.getProperty("style"); //NOI18N
1293: if (facetProp != null) {
1294: String stylePrefix = "display: block; text-align: "; //NOI18N
1295: String alignValue = "center"; //NOI18N
1296: if (ALIGN_LEFT.equals(paging.align)) {
1297: alignValue = "left"; //NOI18N
1298: } else if (ALIGN_RIGHT.equals(paging.align)) {
1299: alignValue = "right"; //NOI18N
1300: }
1301: facetProp.setValue(stylePrefix + alignValue);
1302:
1303: }
1304: //set the style class
1305: facetProp = facet.getProperty("styleClass"); //NOI18N
1306: if (facetProp != null) {
1307: facetProp
1308: .setValue("footer".equals(facetStr) ? STYLE_CLASS_FOOTER
1309: : STYLE_CLASS_HEADER); //NOI18N
1310: }
1311:
1312: boolean[] buttonRequests = { paging.firstButton,
1313: paging.previousButton, paging.nextButton,
1314: paging.lastButton };
1315: String[] buttonLabels = { paging.firstButtonText,
1316: paging.previousButtonText, paging.nextButtonText,
1317: paging.lastButtonText };
1318: String[] buttonUrls = { paging.firstButtonUrl,
1319: paging.previousButtonUrl, paging.nextButtonUrl,
1320: paging.lastButtonUrl };
1321: String[] navButtonNames = { "FirstButton", "PreviousButton",
1322: "NextButton", "LastButton" }; //NOI18N
1323: String[] defaultButtonUrls = { DEFAULT_FIRST_URL,
1324: DEFAULT_PREVIOUS_URL, DEFAULT_NEXT_URL,
1325: DEFAULT_LAST_URL };
1326: String[] defaultButtonImgs = { DEFAULT_FIRST_IMG,
1327: DEFAULT_PREVIOUS_IMG, DEFAULT_NEXT_IMG,
1328: DEFAULT_LAST_IMG };
1329: String facetPrefix = facetStr.equals("header") ? "Header"
1330: : "Footer"; //NOI18N
1331:
1332: for (int i = 0; i < buttonRequests.length; i++) {
1333: if (buttonRequests[i]) {
1334: //create a button
1335: DesignBean btn = context.createBean(
1336: HtmlCommandButton.class.getName(), facet, null);
1337: btn.setInstanceName(tableBean.getInstanceName()
1338: + facetPrefix + navButtonNames[i]); //NOI18N
1339: btn.getProperty("immediate").setValue(Boolean.TRUE); //NOI18N
1340: if (BUTTON_TEXT.equals(paging.navigation)
1341: && buttonLabels[i] != null
1342: && buttonLabels[i].length() > 0) {
1343: if (isJsfELSyntax(buttonLabels[i])) {
1344: btn.getProperty("value").setValueSource(
1345: buttonLabels[i]); //NOI18N
1346: } else {
1347: btn.getProperty("value").setValue(
1348: buttonLabels[i]); //NOI18N
1349: }
1350: }
1351: if (BUTTON_IMAGE.equals(paging.navigation)
1352: && buttonUrls[i] != null
1353: && buttonUrls[i].length() > 0) {
1354: String urlToUse = buttonUrls[i];
1355: if (buttonUrls[i].equals(defaultButtonUrls[i])) {
1356: boolean resourceAlreadyInProject = false;
1357:
1358: //HACK? The designtime API should probably expose whether the resource is already in the project
1359: URL localFileUrl = context
1360: .resolveResource(buttonUrls[i]); // like file://C:/Documents and Settings/blah/blah/.../paging_first.png
1361: String localFileUrlStr = localFileUrl
1362: .toString();
1363: final String protocol = "file:/"; //NOI18N
1364: if (localFileUrlStr.startsWith(protocol)) {
1365: String localFilePath = localFileUrlStr
1366: .substring(protocol.length()); // like C:/Documents and Settings/blah/blah/.../paging_first.png
1367: //possibly with leading /
1368: localFilePath = localFilePath.replaceAll(
1369: "%20", " ");
1370: if (localFilePath.startsWith("/")
1371: && localFilePath.length() > 1) {
1372: localFilePath = localFilePath
1373: .substring(1, localFilePath
1374: .length()); //trim leading /
1375: }
1376: File localFile = new File(localFilePath);
1377: resourceAlreadyInProject = localFile
1378: .exists();
1379: }
1380:
1381: if (!resourceAlreadyInProject) {
1382: URL urlToDefaultImage = HtmlDataTableState.class
1383: .getResource(defaultButtonImgs[i]);
1384: try {
1385: urlToUse = context.addResource(
1386: urlToDefaultImage, true);
1387: } catch (IOException ioe) {
1388: ioe.printStackTrace();
1389: }
1390: }
1391: }
1392: if (isJsfELSyntax(urlToUse)) {
1393: btn.getProperty("image").setValueSource(
1394: urlToUse);
1395: } else {
1396: btn.getProperty("image").setValue(urlToUse);
1397: }
1398: }
1399:
1400: //get the btn's action event
1401: DesignEvent actionEvent = getActionEvent(btn);
1402:
1403: //set the handler name. a NullPointerException will be thrown if insync did not provide an action event.
1404: actionEvent.setHandlerName(tableBean.getInstanceName()
1405: + PAGING_HANDLER_SUFFIXES[i]); //like dataTable47_previousPageAction
1406:
1407: //set the handler source.
1408: String handlerMethodSource = "//not implemented\n"; //NOI18N
1409: switch (i) {
1410: case 0:
1411: handlerMethodSource = getFirstButtonHandlerSource();
1412: break;
1413: case 1:
1414: handlerMethodSource = getPreviousButtonHandlerSource();
1415: break;
1416: case 2:
1417: handlerMethodSource = getNextButtonHandlerSource();
1418: break;
1419: case 3:
1420: handlerMethodSource = getLastButtonHandlerSource();
1421: break;
1422: }
1423: //System.err.println("HtmlDataTableState.createNavPanel(" + facetStr + "): actionEvent.handlerMethodSource will be:\n" + handlerMethodSource + "!"); //NOI18N
1424: actionEvent.setHandlerMethodSource(handlerMethodSource);
1425: //System.err.println("HtmlDataTableState.createNavPanel(" + facetStr + "): actionEvent.handlerName:" + actionEvent.getHandlerName() + "!"); //NOI18N
1426: //System.err.println("HtmlDataTableState.createNavPanel(" + facetStr + "): actionEvent.handlerMethodSource:\n" + actionEvent.getHandlerMethodSource() + "!"); //NOI18N
1427: }
1428: }
1429: }
1430:
1431: private String getFirstButtonHandlerSource() {
1432: StringBuffer sb = new StringBuffer("\n"); //NOI18N
1433: sb.append(" " + tableBean.getInstanceName()
1434: + ".setFirst(0);\n"); //NOI18N
1435: sb.append(" return null;"); //NOI18N
1436: return sb.toString();
1437: }
1438:
1439: private String getPreviousButtonHandlerSource() {
1440: StringBuffer sb = new StringBuffer("\n"); //NOI18N
1441: String tbInstName = tableBean.getInstanceName();
1442: sb.append(" int first = " + tbInstName
1443: + ".getFirst() - " + tbInstName + //NOI18N
1444: ".getRows();\n"); //NOI18N
1445: sb.append(" if (first < 0) {\n"); //NOI18N
1446: sb.append(" first = 0;\n"); //NOI18N
1447: sb.append(" }\n"); //NOI18N
1448: sb.append(" " + tbInstName + ".setFirst(first);\n"); //NOI18N
1449: sb.append(" return null;"); //NOI18N
1450: return sb.toString();
1451: }
1452:
1453: private String getNextButtonHandlerSource() {
1454: StringBuffer sb = new StringBuffer("\n"); //NOI18N
1455: String tbInstName = tableBean.getInstanceName();
1456: sb.append(" int first = " + tbInstName
1457: + ".getFirst() + " + tbInstName + //NOI18N
1458: ".getRows();\n"); //NOI18N
1459: sb.append(" " + tbInstName + ".setRowIndex(first);\n"); //NOI18N
1460: sb.append(" if (" + tbInstName
1461: + ".isRowAvailable()) {\n"); //NOI18N
1462: sb.append(" " + tbInstName + ".setFirst(first);\n"); //NOI18N
1463: sb.append(" }\n"); //NOI18N
1464: sb.append(" return null;"); //NOI18N
1465: return sb.toString();
1466: }
1467:
1468: private String getLastButtonHandlerSource() {
1469: StringBuffer sb = new StringBuffer("\n"); //NOI18N
1470: String tbInstName = tableBean.getInstanceName();
1471: sb.append(" int first = " + tbInstName
1472: + ".getFirst();\n"); //NOI18N
1473: sb.append(" while (true) {\n"); //NOI18N
1474: sb.append(" " + tbInstName
1475: + ".setRowIndex(first + 1);\n"); //NOI18N
1476: sb.append(" if (" + tbInstName
1477: + ".isRowAvailable()) {\n"); //NOI18N
1478: sb.append(" first++;\n"); //NOI18N
1479: sb.append(" } else {\n"); //NOI18N
1480: sb.append(" break;\n"); //NOI18N
1481: sb.append(" }\n"); //NOI18N
1482: sb.append(" }\n"); //NOI18N
1483: sb.append(" " + tbInstName
1484: + ".setFirst(first - (first % " + tbInstName + //NOI18N
1485: ".getRows()));\n"); //NOI18N
1486: sb.append(" return null;"); //NOI18N
1487: return sb.toString();
1488: }
1489:
1490: public void dumpState(PrintStream out) {
1491: //out.println("datatable: " + instanceName); //NOI18N
1492: out.println(" sourceBean: " + sourceBean); //NOI18N
1493: out.println(" var: " + varName); //NOI18N
1494: ResultSetColumn[] rsca = rsinfo.getColumns();
1495: out.println(" columns: (" + rsca.length + " total)"); //NOI18N
1496: for (int i = 0; i < rsca.length; i++) {
1497: ResultSetColumn rsc = rsca[i];
1498: out.println(" column: [" + rsc.tableName + DOT
1499: + rsc.columnName + "]"); //NOI18N
1500: //out.println(" class: " + rsc.columnClassName); //NOI18N
1501: //out.println(" sqlType: " + rsc.columnSqlType + ": " + rsc.columnSqlTypeName); //NOI18N
1502: }
1503: out.println(" display:"); //NOI18N
1504: out.println(" rows: " + paging.rows); //NOI18N
1505: DisplayColumn[] dca = display.getColumns();
1506: out.println(" columns: (" + dca.length + " total)"); //NOI18N
1507: for (int i = 0; i < dca.length; i++) {
1508: DisplayColumn dc = dca[i];
1509: out.println(" column: " + dc.columnInstanceName); //NOI18N
1510: //out.println(" compInstanceName: " + dc.compInstanceName); //NOI18N
1511: out.println(" class: " + dc.compClassName); //NOI18N
1512: out.println(" valueRef: " + dc.compValueRef); //NOI18N
1513: //out.println(" converter: " + dc.compConverter); //NOI18N
1514: //out.println(" validator: " + dc.compValidator); //NOI18N
1515: out.println(" header: " + dc.headerText); //NOI18N
1516: //out.println(" headerLink: " + dc.headerLink); //NOI18N
1517: out.println(" footer: " + dc.footerText); //NOI18N
1518: out.println(" itemText: " + dc.itemText); //NOI18N
1519: }
1520: }
1521: }
|