private void _createFieldDebugInfo(FacesContext facesContext,
            final String field, Object oldValue, 
            Object newValue, final int skipStackTaceElements)
    {
        if (oldValue == null && newValue == null)
        {
            // both values are null, not interesting and can
            // happen a lot in UIData with saving and restoring state
            return;
        }
        
        if (facesContext.getViewRoot() == null)
        {
            // No viewRoot set, it is creating component, 
            // so it is not possible to calculate the clientId, 
            // abort processing because the interesting part will
            // happen later.
            return;
        }
        
        if (getParent() == null || !isInView())
        {
            //Skip if no parent or is not in view
            return;
        }
        
        // convert Array values into a more readable format
        if (oldValue != null && oldValue.getClass().isArray() && Object[].class.isAssignableFrom(oldValue.getClass()))
        {
            oldValue = Arrays.deepToString((Object[]) oldValue);
        }
        if (newValue != null && newValue.getClass().isArray() && Object[].class.isAssignableFrom(newValue.getClass()))
        {
            newValue = Arrays.deepToString((Object[]) newValue);
        }
        
        // use Throwable to get the current call stack
        Throwable throwableHelper = new Throwable();
        StackTraceElement[] stackTraceElements = throwableHelper.getStackTrace();
        List<StackTraceElement> debugStackTraceElements = new LinkedList<StackTraceElement>();
        
        // + 1 because this method should also be skipped
        for (int i = skipStackTaceElements + 1; i < stackTraceElements.length; i++)
        {
            debugStackTraceElements.add(stackTraceElements[i]);
            
            if (FacesServlet.class.getCanonicalName()
                    .equals(stackTraceElements[i].getClassName()))
            {
                // stop after the FacesServlet
                break;
            }
        }
        
        // create the debug-info array
        // structure:
        //     - 0: phase
        //     - 1: old value
        //     - 2: new value
        //     - 3: StackTraceElement List
        // NOTE that we cannot create a class here to encapsulate this data,
        // because this is not on the spec and the class would not be available in impl.
        Object[] debugInfo = new Object[4];
        debugInfo[0] = facesContext.getCurrentPhaseId();
        debugInfo[1] = oldValue;
        debugInfo[2] = newValue;
        debugInfo[3] = debugStackTraceElements;
        
        // add the debug info
        _getFieldDebugInfos(field).add(debugInfo);
    }
private void _createFieldDebugInfo ( FacesContext facesContext , final String field , Object oldValue , Object newValue , final int skipStackTaceElements ) { if ( oldValue == null && newValue == null ) { return ; } if ( facesContext . getViewRoot ( ) == null ) { return ; } if ( getParent ( ) == null || ! isInView ( ) ) { return ; } if ( oldValue != null && oldValue . getClass ( ) . isArray ( ) && Object [ ] . class . isAssignableFrom ( oldValue . getClass ( ) ) ) { oldValue = Arrays . deepToString ( ( Object [ ] ) oldValue ) ; } if ( newValue != null && newValue . getClass ( ) . isArray ( ) && Object [ ] . class . isAssignableFrom ( newValue . getClass ( ) ) ) { newValue = Arrays . deepToString ( ( Object [ ] ) newValue ) ; } Throwable throwableHelper = new Throwable ( ) ; StackTraceElement [ ] stackTraceElements = throwableHelper . getStackTrace ( ) ; List < StackTraceElement > debugStackTraceElements = new LinkedList < StackTraceElement > ( ) ; for ( int i = skipStackTaceElements + 1 ; i < stackTraceElements . length ; i ++ ) { debugStackTraceElements . add ( stackTraceElements [ i ] ) ; if ( FacesServlet . class . getCanonicalName ( ) . equals ( stackTraceElements [ i ] . getClassName ( ) ) ) { break ; } } Object [ ] debugInfo = new Object [ 4 ] ; debugInfo [ 0 ] = facesContext . getCurrentPhaseId ( ) ; debugInfo [ 1 ] = oldValue ; debugInfo [ 2 ] = newValue ; debugInfo [ 3 ] = debugStackTraceElements ; _getFieldDebugInfos ( field ) . add ( debugInfo ) ; }
Creates the field debug-info for the given field, which changed
from oldValue to newValue.

@param facesContext
@param field
@param oldValue
@param newValue
@param skipStackTaceElements How many StackTraceElements should be skipped
when the calling function will be determined.