Save This Page
Home » tomahawk-1.1.6-src » org.apache.myfaces.component.html » ext » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one
    3    * or more contributor license agreements.  See the NOTICE file
    4    * distributed with this work for additional information
    5    * regarding copyright ownership.  The ASF licenses this file
    6    * to you under the Apache License, Version 2.0 (the
    7    * "License"); you may not use this file except in compliance
    8    * with the License.  You may obtain a copy of the License at
    9    *
   10    *   http://www.apache.org/licenses/LICENSE-2.0
   11    *
   12    * Unless required by applicable law or agreed to in writing,
   13    * software distributed under the License is distributed on an
   14    * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   15    * KIND, either express or implied.  See the License for the
   16    * specific language governing permissions and limitations
   17    * under the License.
   18    */
   19   package org.apache.myfaces.component.html.ext;
   20   
   21   import java.io.IOException;
   22   import java.sql.ResultSet;
   23   import java.util.ArrayList;
   24   import java.util.Collection;
   25   import java.util.HashMap;
   26   import java.util.Iterator;
   27   import java.util.List;
   28   import java.util.Map;
   29   
   30   import javax.faces.application.FacesMessage;
   31   import javax.faces.component.EditableValueHolder;
   32   import javax.faces.component.NamingContainer;
   33   import javax.faces.component.UIComponent;
   34   import javax.faces.context.FacesContext;
   35   import javax.faces.el.ValueBinding;
   36   import javax.faces.model.ArrayDataModel;
   37   import javax.faces.model.DataModel;
   38   import javax.faces.model.ListDataModel;
   39   import javax.faces.model.ResultDataModel;
   40   import javax.faces.model.ResultSetDataModel;
   41   import javax.faces.model.ScalarDataModel;
   42   import javax.servlet.jsp.jstl.sql.Result;
   43   
   44   import org.apache.myfaces.custom.ExtendedComponentBase;
   45   
   46   /**
   47    * Reimplement all UIData functionality to be able to have (protected) access
   48    * the internal DataModel.
   49    *
   50    * @author Manfred Geiler (latest modification by $Author: grantsmith $)
   51    * @version $Revision: 472630 $ $Date: 2006-11-08 21:40:03 +0100 (Mi, 08 Nov 2006) $
   52    */
   53   public abstract class HtmlDataTableHack extends
   54                   javax.faces.component.html.HtmlDataTable implements ExtendedComponentBase
   55   {
   56       private Map _dataModelMap = new HashMap();
   57   
   58       // will be set to false if the data should not be refreshed at the beginning of the encode phase
   59       private boolean _isValidChilds = true;
   60   
   61       // holds for each row the states of the child components of this UIData
   62       private Map _rowStates = new HashMap();
   63   
   64       // contains the initial row state which is used to initialize each row
   65       private Object _initialDescendantComponentState = null;
   66   
   67       // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
   68       // Every field and method from here is identical to UIData !!!!!!!!!
   69       // EXCEPTION: we can create a DataModel from a Collection
   70   
   71       private static final Class OBJECT_ARRAY_CLASS = (new Object[0]).getClass();
   72   
   73       private static final boolean DEFAULT_PRESERVEROWSTATES = false;
   74   
   75       private int _rowIndex = -1;
   76       private Boolean _forceId;
   77   
   78       private Boolean _preserveRowStates;
   79   
   80       public boolean isRowAvailable()
   81       {
   82           return getDataModel().isRowAvailable();
   83       }
   84   
   85       public int getRowCount()
   86       {
   87           return getDataModel().getRowCount();
   88       }
   89   
   90       public Object getRowData()
   91       {
   92           return getDataModel().getRowData();
   93       }
   94   
   95       public int getRowIndex()
   96       {
   97           return _rowIndex;
   98       }
   99       
  100       /**
  101        * Hack since RI does not call getRowIndex()
  102        */
  103       public String getClientId(FacesContext context)
  104       {
  105           String clientId = super.getClientId(context);
  106           int rowIndex = getRowIndex();
  107           if (rowIndex == -1)
  108           {
  109               return clientId;
  110           }
  111           // the following code tries to avoid rowindex to be twice in the client id
  112           int index = clientId.lastIndexOf(NamingContainer.SEPARATOR_CHAR);
  113           if(index != -1)
  114           {
  115               String rowIndexString = clientId.substring(index + 1);
  116               try
  117               {
  118                   if(Integer.parseInt(rowIndexString) == rowIndex)
  119                   {
  120                       return clientId;
  121                   }
  122               }
  123               catch(NumberFormatException e)
  124               {
  125                   return clientId + NamingContainer.SEPARATOR_CHAR + rowIndex;
  126               }
  127           }
  128           return clientId + NamingContainer.SEPARATOR_CHAR + rowIndex;
  129       }
  130   
  131       /**
  132        * @see javax.faces.component.UIData#processUpdates(javax.faces.context.FacesContext)
  133        */
  134       public void processUpdates(FacesContext context)
  135       {
  136           super.processUpdates(context);
  137           // check if a update model error forces the render response for our data
  138           if (context.getRenderResponse())
  139           {
  140               _isValidChilds = false;
  141           }
  142       }
  143   
  144       /**
  145        * @see javax.faces.component.UIData#processValidators(javax.faces.context.FacesContext)
  146        */
  147       public void processValidators(FacesContext context)
  148       {
  149           super.processValidators(context);
  150           // check if a validation error forces the render response for our data
  151           if (context.getRenderResponse())
  152           {
  153               _isValidChilds = false;
  154           }
  155       }
  156   
  157       /**
  158        * @see javax.faces.component.UIData#encodeBegin(javax.faces.context.FacesContext)
  159        */
  160       public void encodeBegin(FacesContext context) throws IOException
  161       {
  162           _initialDescendantComponentState = null;
  163           if (_isValidChilds && !hasErrorMessages(context))
  164           {
  165               //Refresh DataModel for rendering:
  166               _dataModelMap.clear();
  167               if (!isPreserveRowStates())
  168               {
  169               	_rowStates.clear();
  170               }
  171           }
  172           super.encodeBegin(context);
  173       }
  174   
  175       public void setPreserveRowStates(boolean preserveRowStates)
  176       {
  177           _preserveRowStates = Boolean.valueOf(preserveRowStates);
  178       }
  179   
  180       public boolean isPreserveRowStates()
  181       {
  182           if (_preserveRowStates != null)
  183               return _preserveRowStates.booleanValue();
  184           ValueBinding vb = getValueBinding("preserveRowStates");
  185           Boolean v = vb != null ? (Boolean) vb.getValue(getFacesContext()) : null;
  186           return v != null ? v.booleanValue() : DEFAULT_PRESERVEROWSTATES;
  187       }
  188   
  189       protected boolean hasErrorMessages(FacesContext context)
  190       {
  191           for(Iterator iter = context.getMessages(); iter.hasNext();)
  192           {
  193               FacesMessage message = (FacesMessage) iter.next();
  194               if(FacesMessage.SEVERITY_ERROR.compareTo(message.getSeverity()) <= 0)
  195               {
  196                   return true;
  197               }
  198           }
  199           return false;
  200       }
  201   
  202       /**
  203        * @see javax.faces.component.UIComponentBase#encodeEnd(javax.faces.context.FacesContext)
  204        */
  205       public void encodeEnd(FacesContext context) throws IOException
  206       {
  207           setRowIndex(-1);
  208           super.encodeEnd(context);
  209       }
  210   
  211       public void setRowIndex(int rowIndex)
  212       {
  213           if (rowIndex < -1)
  214           {
  215               throw new IllegalArgumentException("rowIndex is less than -1");
  216           }
  217   
  218           if (_rowIndex == rowIndex)
  219           {
  220               return;
  221           }
  222   
  223           FacesContext facesContext = getFacesContext();
  224   
  225           if (_rowIndex == -1)
  226           {
  227               if (_initialDescendantComponentState == null)
  228               {
  229                   _initialDescendantComponentState = saveDescendantComponentStates(getChildren()
  230                                   .iterator(), false);
  231               }
  232           }
  233           else
  234           {
  235               _rowStates.put(getClientId(facesContext),
  236                               saveDescendantComponentStates(getChildren()
  237                                               .iterator(), false));
  238           }
  239   
  240           _rowIndex = rowIndex;
  241   
  242           DataModel dataModel = getDataModel();
  243           dataModel.setRowIndex(rowIndex);
  244   
  245           String var = getVar();
  246           if (rowIndex == -1)
  247           {
  248               if (var != null)
  249               {
  250                   facesContext.getExternalContext().getRequestMap().remove(var);
  251               }
  252           }
  253           else
  254           {
  255               if (var != null)
  256               {
  257                   if (isRowAvailable())
  258                   {
  259                       Object rowData = dataModel.getRowData();
  260                       facesContext.getExternalContext().getRequestMap().put(var,
  261                                       rowData);
  262                   }
  263                   else
  264                   {
  265                       facesContext.getExternalContext().getRequestMap().remove(
  266                                       var);
  267                   }
  268               }
  269           }
  270   
  271           if (_rowIndex == -1)
  272           {
  273               restoreDescendantComponentStates(getChildren().iterator(),
  274                               _initialDescendantComponentState, false);
  275           }
  276           else
  277           {
  278               Object rowState = _rowStates.get(getClientId(facesContext));
  279               if (rowState == null)
  280               {
  281                   restoreDescendantComponentStates(getChildren().iterator(),
  282                                   _initialDescendantComponentState, false);
  283               }
  284               else
  285               {
  286                   restoreDescendantComponentStates(getChildren().iterator(),
  287                                   rowState, false);
  288               }
  289           }
  290       }
  291   
  292       protected void restoreDescendantComponentStates(Iterator childIterator,
  293               Object state, boolean restoreChildFacets)
  294       {
  295           Iterator descendantStateIterator = null;
  296           while (childIterator.hasNext())
  297           {
  298               if (descendantStateIterator == null && state != null)
  299               {
  300                   descendantStateIterator = ((Collection) state).iterator();
  301               }
  302               UIComponent component = (UIComponent) childIterator.next();
  303               // reset the client id (see spec 3.1.6)
  304               component.setId(component.getId());
  305               if(!component.isTransient())
  306               {
  307                   Object childState = null;
  308                   Object descendantState = null;
  309                   if (descendantStateIterator != null
  310                           && descendantStateIterator.hasNext())
  311                   {
  312                       Object[] object = (Object[]) descendantStateIterator.next();
  313                       childState = object[0];
  314                       descendantState = object[1];
  315                   }
  316                   if (childState != null && component instanceof EditableValueHolder)
  317                   {
  318                       ((EditableValueHolderState) childState)
  319                               .restoreState((EditableValueHolder) component);
  320                   }
  321                   Iterator childsIterator;
  322                   if (restoreChildFacets)
  323                   {
  324                       childsIterator = component.getFacetsAndChildren();
  325                   }
  326                   else
  327                   {
  328                       childsIterator = component.getChildren().iterator();
  329                   }
  330                   restoreDescendantComponentStates(childsIterator, descendantState,
  331                           true);
  332               }
  333           }
  334       }
  335   
  336       protected Object saveDescendantComponentStates(Iterator childIterator,
  337               boolean saveChildFacets)
  338       {
  339           Collection childStates = null;
  340           while (childIterator.hasNext())
  341           {
  342               if (childStates == null)
  343               {
  344                   childStates = new ArrayList();
  345               }
  346               UIComponent child = (UIComponent) childIterator.next();
  347               if(!child.isTransient())
  348               {
  349                   Iterator childsIterator;
  350                   if (saveChildFacets)
  351                   {
  352                       childsIterator = child.getFacetsAndChildren();
  353                   }
  354                   else
  355                   {
  356                       childsIterator = child.getChildren().iterator();
  357                   }
  358                   Object descendantState = saveDescendantComponentStates(
  359                           childsIterator, true);
  360                   Object state = null;
  361                   if (child instanceof EditableValueHolder)
  362                   {
  363                       state = new EditableValueHolderState(
  364                               (EditableValueHolder) child);
  365                   }
  366                   childStates.add(new Object[] { state, descendantState });
  367               }
  368           }
  369           return childStates;
  370       }
  371   
  372       public void setValueBinding(String name, ValueBinding binding)
  373       {
  374           if (name == null)
  375           {
  376               throw new NullPointerException("name");
  377           }
  378           else if (name.equals("value"))
  379           {
  380               _dataModelMap.clear();
  381           }
  382           else if (name.equals("var") || name.equals("rowIndex"))
  383           {
  384               throw new IllegalArgumentException(
  385                       "You can never set the 'rowIndex' or the 'var' attribute as a value-binding. Set the property directly instead. Name " + name);
  386           }
  387           super.setValueBinding(name, binding);
  388       }
  389   
  390       /**
  391        * @see javax.faces.component.UIData#setValue(java.lang.Object)
  392        */
  393       public void setValue(Object value)
  394       {
  395           super.setValue(value);
  396           _dataModelMap.clear();
  397           _rowStates.clear();
  398           _isValidChilds = true;
  399       }
  400   
  401       protected DataModel getDataModel()
  402       {
  403           DataModel dataModel = null;
  404           String clientID = "";
  405           
  406           UIComponent parent = getParent();
  407           if (parent != null) 
  408           {
  409               clientID = parent.getClientId(getFacesContext());
  410           }
  411           dataModel = (DataModel) _dataModelMap.get(clientID);
  412           if (dataModel == null)
  413           {
  414               dataModel = createDataModel();
  415               _dataModelMap.put(clientID, dataModel);
  416           }               
  417           
  418           return dataModel;
  419       }
  420   
  421       protected void setDataModel(DataModel datamodel)
  422       {
  423           UIComponent parent = getParent();
  424           String clientID = "";
  425           if(parent != null)
  426           {
  427               clientID = parent.getClientId(getFacesContext());
  428           }
  429           _dataModelMap.put(clientID, datamodel);
  430       }
  431   
  432       /**
  433        * Creates a new DataModel around the current value.
  434        */
  435       protected DataModel createDataModel()
  436       {
  437           Object value = getValue();
  438           if (value == null)
  439           {
  440               return EMPTY_DATA_MODEL;
  441           }
  442           else if (value instanceof DataModel)
  443           {
  444               return (DataModel) value;
  445           }
  446           else if (value instanceof List)
  447           {
  448               return new ListDataModel((List) value);
  449           }
  450           // accept a Collection is not supported in the Spec
  451           else if (value instanceof Collection)
  452           {
  453               return new ListDataModel(new ArrayList((Collection) value));
  454           }
  455           else if (OBJECT_ARRAY_CLASS.isAssignableFrom(value.getClass()))
  456           {
  457               return new ArrayDataModel((Object[]) value);
  458           }
  459           else if (value instanceof ResultSet)
  460           {
  461               return new ResultSetDataModel((ResultSet) value);
  462           }
  463           else if (value instanceof Result)
  464           {
  465               return new ResultDataModel((Result) value);
  466           }
  467           else
  468           {
  469               return new ScalarDataModel(value);
  470           }
  471       }
  472       
  473       public Object saveState(FacesContext context)
  474       {
  475           Object[] values = new Object[2];
  476           values[0] = super.saveState(context);
  477           values[1] = _preserveRowStates;
  478           return values;
  479       }
  480       
  481       public void restoreState(FacesContext context, Object state)
  482       {
  483           Object[] values = (Object[])state;
  484           super.restoreState(context, values[0]);
  485           _preserveRowStates = (Boolean) values[1];
  486       }
  487   
  488       private static final DataModel EMPTY_DATA_MODEL = new _SerializableDataModel()
  489       {
  490           public boolean isRowAvailable()
  491           {
  492               return false;
  493           }
  494   
  495           public int getRowCount()
  496           {
  497               return 0;
  498           }
  499   
  500           public Object getRowData()
  501           {
  502               throw new IllegalArgumentException();
  503           }
  504   
  505           public int getRowIndex()
  506           {
  507               return -1;
  508           }
  509   
  510           public void setRowIndex(int i)
  511           {
  512               if (i < -1)
  513                   throw new IndexOutOfBoundsException("Index < 0 : " + i);
  514           }
  515   
  516           public Object getWrappedData()
  517           {
  518               return null;
  519           }
  520   
  521           public void setWrappedData(Object obj)
  522           {
  523               if (obj == null)
  524                   return; //Clearing is allowed
  525               throw new UnsupportedOperationException(this.getClass().getName()
  526                               + " UnsupportedOperationException");
  527           }
  528       };
  529   
  530       private class EditableValueHolderState
  531       {
  532           private final Object _value;
  533           private final boolean _localValueSet;
  534           private final boolean _valid;
  535           private final Object _submittedValue;
  536   
  537           public EditableValueHolderState(EditableValueHolder evh)
  538           {
  539               _value = evh.getLocalValue();
  540               _localValueSet = evh.isLocalValueSet();
  541               _valid = evh.isValid();
  542               _submittedValue = evh.getSubmittedValue();
  543           }
  544   
  545           public void restoreState(EditableValueHolder evh)
  546           {
  547               evh.setValue(_value);
  548               evh.setLocalValueSet(_localValueSet);
  549               evh.setValid(_valid);
  550               evh.setSubmittedValue(_submittedValue);
  551           }
  552       }
  553   
  554       public void setForceId(boolean b)
  555       {
  556           _forceId = Boolean.valueOf(b);
  557       }
  558   
  559       public boolean isForceId()
  560       {
  561           if (_forceId != null) return _forceId.booleanValue();
  562           ValueBinding vb = getValueBinding("forceId");
  563           return vb != null && booleanFromObject(vb.getValue(getFacesContext()), false);
  564       }
  565   
  566       private static boolean booleanFromObject(Object obj, boolean defaultValue)
  567       {
  568           if(obj instanceof Boolean)
  569           {
  570               return ((Boolean) obj).booleanValue();
  571           }
  572           else if(obj instanceof String)
  573           {
  574               return Boolean.valueOf(((String) obj)).booleanValue();
  575           }
  576   
  577           return defaultValue;
  578       }
  579   
  580   }

Save This Page
Home » tomahawk-1.1.6-src » org.apache.myfaces.component.html » ext » [javadoc | source]