/* * � Copyright IBM Corp. 2010 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. */ package com.ibm.xsp.extlib.beans; import java.util.IdentityHashMap; import java.util.Map; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import com.ibm.commons.util.StringUtil; import com.ibm.xsp.component.FacesDataIterator; import com.ibm.xsp.component.UIViewRootEx; import com.ibm.xsp.context.FacesContextEx; import com.ibm.xsp.event.FacesContextListener; import com.ibm.xsp.extlib.component.data.FacesDataIteratorStateHandler; import com.ibm.xsp.extlib.component.data.FacesDataIteratorStateManager; import com.ibm.xsp.extlib.util.RedirectMapUtil; import com.ibm.xsp.util.TypedUtil; /** * Bean that maintains the state of an xe:dataView control or other {@link FacesDataIterator} control. * @author Philippe Riand */ public class ViewStateBean { private static final String RESTORE_KEY = "_xsp.extlib.viewstate.restore"; //$NON-NLS-1$ private static final boolean TRACE = false; private static final long serialVersionUID = 1L; // ====================================================================== // Access to the bean itself // ====================================================================== public static final String BEAN_NAME = "viewStateBean"; //$NON-NLS-1$ public static ViewStateBean get(FacesContext context) { ViewStateBean bean = (ViewStateBean)context.getApplication().getVariableResolver().resolveVariable(context, BEAN_NAME); return bean; } public static ViewStateBean get() { return get(FacesContext.getCurrentInstance()); } public ViewStateBean() { if(TRACE) { System.out.println("ViewStateBean created"); //$NON-NLS-1$ } } private static final String BEAN_DATA = "extlib.people.viewStateBeanData"; //$NON-NLS-1$ private Map<UIComponent,Object> getBeanData(FacesContext context) { Map<UIComponent,Object> data = (Map<UIComponent,Object>)context.getExternalContext().getRequestMap().get(BEAN_DATA); if(data==null) { data = new IdentityHashMap<UIComponent,Object>(); context.getExternalContext().getRequestMap().put(BEAN_DATA,data); FacesContextEx ctx = (FacesContextEx)context; ctx.addRequestListener(new FacesContextListener() { public void beforeRenderingPhase(FacesContext facesContext) { if(!getBeanData(facesContext).isEmpty()) { initFromState(facesContext); } } public void beforeContextReleased(FacesContext facesContext) { if(!getBeanData(facesContext).isEmpty()) { saveState(facesContext); } } }); } return data; } private Map<UIComponent,Object> getBeanData() { return getBeanData(FacesContext.getCurrentInstance()); } public boolean isRestoreState() { FacesContext context = FacesContext.getCurrentInstance(); return RedirectMapUtil.getPushed(context, RESTORE_KEY)!=null; } public void setRestoreState(boolean restoreState) { FacesContext context = FacesContext.getCurrentInstance(); if(restoreState) { RedirectMapUtil.push(context,RESTORE_KEY,Boolean.TRUE); } else { RedirectMapUtil.remove(context,RESTORE_KEY); } } public UIComponent getDataIterator(){ return null; } public void setDataIterator(UIComponent dataIterator){ if(TRACE) { System.out.println("setDataIterator: "+(dataIterator!=null ? "Ok" : "<null>")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } Map<UIComponent,Object> dataIterators = getBeanData(); if(!dataIterators.containsKey(dataIterator)) { dataIterators.put(dataIterator,Boolean.TRUE); } } public void initFromState() { initFromState(FacesContext.getCurrentInstance()); } protected void initFromState(FacesContext context) { // Look if the state should be restored boolean shouldRestoreState = RedirectMapUtil.get(context, RESTORE_KEY)!=null; FacesDataIteratorStateManager m = FacesDataIteratorStateManager.get(); for(UIComponent c: getBeanData(context).keySet()) { Map<String, Object> attributes = TypedUtil.getAttributes(c); if(attributes.get("xsp.initviewstate")==null) { //$NON-NLS-1$ attributes.put("xsp.initviewstate",Boolean.TRUE); //$NON-NLS-1$ String key = findStateKey(context, c); if(StringUtil.isNotEmpty(key)) { m.restoreState(context, c, key, shouldRestoreState); if(TRACE) { System.out.println("View, initFromState: "+key); //$NON-NLS-1$ } } } } } protected void saveState(FacesContext context) { FacesDataIteratorStateManager m = FacesDataIteratorStateManager.get(); Map<UIComponent,Object> dataIterators = getBeanData(context); for(UIComponent c: dataIterators.keySet()) { String key = findStateKey(context, c); if(StringUtil.isNotEmpty(key)) { m.saveState(context, c, key); if(TRACE) { System.out.println("View, saveState: "+key); //$NON-NLS-1$ } } } } protected String findStateKey(FacesContext context, UIComponent iterator) { // // Find if the iterator has a key assigned to it // if (iterator instanceof FacesDataIteratorStateHandler) { // FacesDataIteratorStateHandler itx = (FacesDataIteratorStateHandler) iterator; // String key = itx.getDataIteratorStateKey(); // if (StringUtil.isNotEmpty(key)) { // return key; // } // } // Else return a unique key for this iterator return findDefaultStateKey(context, iterator); } /** * Compose the unique key for an iterator. * @param context * @param iterator * @return */ protected String findDefaultStateKey(FacesContext context, UIComponent c) { if(c instanceof FacesDataIteratorStateHandler) { c = (UIComponent)((FacesDataIteratorStateHandler)c).getFacesDataIterator(context); } if(c!=null) { UIViewRootEx root = (UIViewRootEx)context.getViewRoot(); StringBuilder b = new StringBuilder(); b.append(root.getPageName()); String id = c.getId(); if(StringUtil.isNotEmpty(id)) { b.append('_'); b.append(id); } if(TRACE) { System.out.println("View key: "+b.toString()); //$NON-NLS-1$ } return b.toString(); } return null; } }