GradebookItemTableRenderer.java :  » ERP-CRM-Financial » sakai-2.6.2 » org » sakaiproject » tool » gradebook » jsf » gradebookItemTable » Java Open Source

Java Open Source » ERP CRM Financial » sakai 2.6.2 
sakai 2.6.2 » org » sakaiproject » tool » gradebook » jsf » gradebookItemTable » GradebookItemTableRenderer.java
/**********************************************************************************
 * $URL:$
 * $Id:$
 ***********************************************************************************
 *
 * Copyright (c) 2007, 2008 The Sakai Foundation
 *
 * Licensed under the Educational Community 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.osedu.org/licenses/ECL-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 org.sakaiproject.tool.gradebook.jsf.gradebookItemTable;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.faces.component.UIColumn;
import javax.faces.component.UIComponent;
import javax.faces.component.UIData;
import javax.faces.component.html.HtmlGraphicImage;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.el.ValueBinding;
import javax.faces.render.Renderer;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.myfaces.shared_impl.renderkit.html.HTML;

import org.sakaiproject.tool.gradebook.jsf.FacesUtil;
import org.sakaiproject.tool.gradebook.Category;
import org.sakaiproject.tool.gradebook.GradableObject;
import org.sakaiproject.tool.gradebook.ui.AssignmentGradeRow;
import org.sakaiproject.tool.cover.ToolManager;

public class GradebookItemTableRenderer extends Renderer {

  protected static final Log log = LogFactory.getLog(GradebookItemTableRenderer.class);

  private static final String CURSOR = "cursor:pointer";
  private static final String EXPANDED_IMG = "/images/expand.gif";
  private static final String COLLAPSED_IMG = "/images/collapse.gif";
  
  private HtmlGraphicImage image;
  private boolean expanded;
  private String path;
  
  private static final String EXPAND_ALT = "cat_expanded";
  private static final String EXPAND_TITLE = "cat_view_collapse";
  private static final String COLLAPSE_ALT = "cat_collapsed";
  private static final String COLLAPSE_TITLE = "cat_view_expand";
  
  String imgExpandAlt;
  String imgExpandTitle;
  String imgCollapseAlt;
  String imgCollapseTitle;
  

  /**
   * This component renders its children
   * @return true
   */
  public boolean getRendersChildren()
  {
    return true;
  }

  public boolean supportsComponentType(UIComponent component)
  {
    return (component instanceof org.apache.myfaces.component.html.ext.HtmlDataTable);
  }

  public void encodeBegin(FacesContext context, UIComponent component) throws IOException
  {  
    if(!component.isRendered()){
      //tool_bar tag is not to be rendered, return now
      return;
    }
    UIData data = (UIData) component;

    //Begin Rendering
    ResponseWriter writer = context.getResponseWriter();

    //Render Header Facets
    writer.startElement("table", data);

    String styleClass = (String) data.getAttributes().get("styleClass");
    if (styleClass != null) {
      writer.writeAttribute("class", styleClass, "styleClass");
    }
    String cellspacing = (String) data.getAttributes().get("cellspacing");
    if (cellspacing != null) {
      writer.writeAttribute("cellspacing", cellspacing, null);
    }
    String cellpadding = (String) data.getAttributes().get("cellpadding");
    if (cellpadding != null) {
      writer.writeAttribute("cellpadding", cellpadding, null);
    }
    
    String headerClasses[] = getHeaderClasses(data);
    int headerStyle = 0;
    int headerStyles = headerClasses.length;
    
    
    writer.writeText("\n", null);
    
    String expandedValue = (String) data.getAttributes().get("expanded");
    expanded = false;
    if(expandedValue != null && expandedValue.equals("true"))
      expanded = true;
    else
      expanded = false;

    path = context.getExternalContext().getRequestContextPath();
    
    imgExpandAlt = FacesUtil.getLocalizedString(EXPAND_ALT);
    imgExpandTitle = FacesUtil.getLocalizedString(EXPAND_TITLE);
    imgCollapseAlt = FacesUtil.getLocalizedString(COLLAPSE_ALT);
    imgCollapseTitle = FacesUtil.getLocalizedString(COLLAPSE_TITLE);

    image = new HtmlGraphicImage();
    if (expanded) {
      image.setValue(path + EXPANDED_IMG);
      image.setAlt(imgExpandAlt);
      image.setTitle(imgExpandTitle);
    }
    else {
      image.setValue(path + COLLAPSED_IMG);
      image.setAlt(imgCollapseAlt);
      image.setTitle(imgCollapseTitle);
    }

    // Render the header facets (if any)
    UIComponent header = data.getFacet("header");
    int headerFacets = getFacetCount(data, "header");
    if ((header != null) || (headerFacets > 0)) {
      writer.startElement("thead", data);
      writer.writeText("\n", null);
    }
    if (header != null) {
      writer.startElement("tr", header);
      writer.startElement("th", header);
      writer.writeAttribute("colspan", "" + getColumnCount(data), null);
      writer.writeAttribute("scope", "colgroup", null);
      encodeRecursive(context, header);
      writer.endElement("th");
      writer.endElement("tr");
      writer.writeText("\n", null);
    }
    if (headerFacets > 0) {
      writer.startElement("tr", data);
      writer.writeText("\n", null);

      Iterator columns = getColumns(data);
      while (columns.hasNext()) {
        UIColumn column = (UIColumn) columns.next();
        writer.startElement("th", column);
        if (headerStyles > 0 && headerStyle < headerStyles) {
          writer.writeAttribute("class", headerClasses[headerStyle++], "headerClass");
        }
        writer.writeAttribute("scope", "col", null);
        if (column.getId().endsWith("_toggle")) {
          // get the number of toggles for "expand/collapse all" js
          int numItems = getNumDataItemsForToggle(context, component);
          String onclickText = "javascript:showHideAll('" + numItems + "', '" +  path + "', '" + imgExpandAlt  + "', '" + imgCollapseAlt  + "', '" + imgExpandTitle + "', '" + imgCollapseTitle + "');";
          
          writer.startElement(HTML.IMG_ELEM, image);
          writer.writeURIAttribute("src", image.getValue(), null);
          writer.writeURIAttribute("onclick", onclickText, null);
          writer.writeURIAttribute("style", CURSOR, null);
          writer.writeURIAttribute("alt", image.getAlt(), null);
          writer.writeURIAttribute("title", image.getTitle(), null);
          writer.writeURIAttribute("id", "expandCollapseAll", null);
          writer.endElement(HTML.IMG_ELEM);
        }
        UIComponent facet = column.getFacet("header");
        if (facet != null) {
          encodeRecursive(context, facet);
        }
        writer.endElement("th");
        writer.writeText("\n", null);
      }
      writer.endElement("tr");
      writer.writeText("\n", null);
    }
    if ((header != null) || (headerFacets > 0)) {
      writer.endElement("thead");
      writer.writeText("\n", null);
    }

    // Render the footer facets (if any)
    UIComponent footer = data.getFacet("footer");
    int footerFacets = getFacetCount(data, "footer");
    String footerClass = (String) data.getAttributes().get("footerClass");
    if ((footer != null) || (footerFacets > 0)) {
      writer.startElement("tfoot", data);
      writer.writeText("\n", null);
    }
    if (footer != null) {
      writer.startElement("tr", footer);
      writer.startElement("td", footer);
      if (footerClass != null) {
        writer.writeAttribute("class", footerClass, "footerClass");
      }
      writer.writeAttribute("colspan", "" + getColumnCount(data), null);
      encodeRecursive(context, footer);
      writer.endElement("td");
      writer.endElement("tr");
      writer.writeText("\n", null);
    }
    if (footerFacets > 0) {
      writer.startElement("tr", data);
      writer.writeText("\n", null);
      Iterator columns = getColumns(data);
      while (columns.hasNext()) {
        UIColumn column = (UIColumn) columns.next();
        writer.startElement("td", column);
        if (footerClass != null) {
          writer.writeAttribute("class", footerClass, "footerClass");
        }
        UIComponent facet = column.getFacet("footer");
        if (facet != null) {
          encodeRecursive(context, facet);
        }
        writer.endElement("td");
        writer.writeText("\n", null);
      }
      writer.endElement("tr");
      writer.writeText("\n", null);
    }
    if ((footer != null) || (footerFacets > 0)) {
      writer.endElement("tfoot");
      writer.writeText("\n", null);
    }
  }

  /**
   * We put all our processing in the encodeChildren method
   * @param context
   * @param component
   * @throws IOException
   */
  public void encodeChildren(FacesContext context, UIComponent component)
  throws IOException
  {

    if ((context == null) || (component == null)) {
      return;
    }
    if (!component.isRendered()) {
      return;
    }

    UIData data = (UIData) component;

    ValueBinding gbItemsBinding = component.getValueBinding("value");
    List gbItemList = (List)gbItemsBinding.getValue(context);

    // Set up variables we will need
    String columnClasses[] = getColumnClasses(data);
    int columnStyle = 0;
    int columnStyles = columnClasses.length;
    String rowClasses[] = getRowClasses(data);
    int rowStyles = rowClasses.length;
    ResponseWriter writer = context.getResponseWriter();
    Iterator kids = null;
    Iterator grandkids = null;

    // Iterate over the rows of data that are provided
    int processed = 0;
    int rowIndex = data.getFirst() - 1;
    int rows = data.getRows();
    int rowStyle = 0;

    

    writer.startElement("tbody", component);
    writer.writeText("\n", null);
    int hideDivNo = 0;
    while (true) {
      Category gbCategory = null;

      boolean isCategory = false;
      boolean isAssignment = false;
      boolean isCourseGrade = false;
      boolean isGradeRow = false;
      
      if(gbItemList !=null && gbItemList.size() > (rowIndex+1) && rowIndex > -2)
      {
        Object gbItem = gbItemList.get(rowIndex+1);
        if (gbItem instanceof Category) {
          isCategory = true;
          isCourseGrade = false;
          isAssignment = false;
          gbCategory = (Category) gbItem;
        }
        else if (gbItem instanceof GradableObject){
          isCategory = false;
          GradableObject go = (GradableObject) gbItem;
          if (go.isAssignment()) {
            isAssignment = true;
            isCourseGrade = true;
          }
          else {
            isAssignment = false;
            isCourseGrade = true;
          }
        }
        else if (gbItem instanceof AssignmentGradeRow) {
          isCategory = false;
          isCourseGrade = false;
          isAssignment = false;
          isGradeRow = true;
        }
        else {
          throw new IllegalArgumentException("Invalid class passed to renderer: " + gbItem.getClass());
        }
      }
      
      boolean hasChildBoolean = false;
      int childNo = 0;
      if(isCategory && gbCategory != null && gbItemList.size() > rowIndex + 2)
      {
        for (int i=rowIndex+2; i < gbItemList.size(); i++) {
          Object nextItem = gbItemList.get(i);
          if (nextItem instanceof GradableObject) {
            GradableObject nextGo = (GradableObject) nextItem;
            if (nextGo.isAssignment()) {
              hasChildBoolean = true;
              childNo++;
            } else {
              break;
            }
          } 
          else if (nextItem instanceof AssignmentGradeRow) {
            hasChildBoolean = true;
            childNo++;
          } else if (nextItem instanceof Category) {
            break;
          }
        }
      } 

      // Have we displayed the requested number of rows?
      if ((rows > 0) && (++processed > rows)) {
        break;
      }
      // Select the current row
      data.setRowIndex(++rowIndex);
      if (!data.isRowAvailable()) {
        break; // Scrolled past the last row
      }

      // Render the beginning of this row
      writer.startElement("tr", data);
      if(isAssignment || isGradeRow)
      {
        String assignId = "_id_" + new Integer(hideDivNo).toString() + "__hide_division_";
        writer.writeAttribute("id", assignId, null);
        if (!expanded) 
          writer.writeAttribute("style", "display:none;", null);
      }

      if (rowStyles > 0) {
        writer.writeAttribute("class", rowClasses[rowStyle++],
        "rowClasses");
        if (rowStyle >= rowStyles) {
          rowStyle = 0;
        }
      }
      writer.writeText("\n", null);

      // Iterate over the child UIColumn components for each row
      columnStyle = 0;
      kids = getColumns(data);
      while (kids.hasNext()) {

        // Identify the next renderable column
        UIColumn column = (UIColumn) kids.next();

        // Render the beginning of this cell
        writer.startElement("td", column);
        if (columnStyles > 0) {
          writer.writeAttribute("class", columnClasses[columnStyle++],
          "columnClasses");
          if (columnStyle >= columnStyles) {
            columnStyle = 0;
          }
        }

        if((isAssignment || isCourseGrade || isCategory || isGradeRow) 
            && column.getId().endsWith("_toggle"))
        {
          if(hasChildBoolean && isCategory)
          {
            String imgId = "_id_" + new Integer(hideDivNo).toString() + "__img_hide_division_";
            String hideTr = "";
            for(int i=0; i<childNo; i++)
            {
              hideTr += "javascript:showHideDiv('_id_" + new Integer(hideDivNo+i).toString() + 
                "', '" +  path + "', '" + imgExpandAlt  + "', '" + imgCollapseAlt  + "', '" + imgExpandTitle + "', '" + imgCollapseTitle + "');";
            }
            
            hideTr += "mySetMainFrameHeight('Main" + ToolManager.getCurrentPlacement().getId().replace('-','x') + "');";

            writer.startElement(HTML.IMG_ELEM, image);
            writer.writeURIAttribute("src", image.getValue(), null);
            writer.writeURIAttribute("onclick", hideTr, null);
            writer.writeURIAttribute("style", CURSOR, null);
            writer.writeURIAttribute("alt", image.getAlt(), null);
            writer.writeURIAttribute("title", image.getTitle(), null);
            writer.writeURIAttribute("id", imgId, null);
            writer.endElement(HTML.IMG_ELEM);
          }
          
          writer.endElement("td");
          continue;
        }


        // Render the contents of this cell by iterating over
        // the kids of our kids
        grandkids = getChildren(column);
        while (grandkids.hasNext()) {
          encodeRecursive(context, (UIComponent) grandkids.next());
        }

        // Render the ending of this cell
        writer.endElement("td");
        writer.writeText("\n", null);

      }

      // Render the ending of this row
      writer.endElement("tr");
      writer.writeText("\n", null);

      if(isAssignment || isGradeRow)
      {
        if(expanded)
        {
          writer.write("<script type=\"text/javascript\">");
          writer.write("  showHideDiv('_id_" + new Integer(hideDivNo).toString() +
              "', '" +  path + "', '" + imgExpandAlt  + "', '" + imgCollapseAlt  + "', '" + imgExpandTitle + "', '" + imgCollapseTitle + "');");
          writer.write("</script>");
        }

        hideDivNo++;
      }
    }
    writer.endElement("tbody");
    writer.writeText("\n", null);

    // Clean up after ourselves
    data.setRowIndex(-1);
    if (log.isTraceEnabled()) {
      log.trace("End encoding children " +
          component.getId());
    }
  }

  public void encodeEnd(FacesContext context, UIComponent component)
  throws IOException {

    if ((context == null) || (component == null)) {
      return;
    }
    if (!component.isRendered()) {
      return;
    }
    UIData data = (UIData) component;
    data.setRowIndex(-1);
    ResponseWriter writer = context.getResponseWriter();

    // Render the ending of this table
    writer.endElement("table");
    writer.writeText("\n", null);
  }

  /**
   * <p>Return an Iterator over the <code>UIColumn</code> children
   * of the specified <code>UIData</code> that have a
   * <code>rendered</code> property of <code>true</code>.</p>
   *
   * @param data <code>UIData</code> for which to extract children
   */
  private Iterator getColumns(UIData data) {

    List results = new ArrayList();
    Iterator kids = data.getChildren().iterator();
    while (kids.hasNext()) {
      UIComponent kid = (UIComponent) kids.next();
      if ((kid instanceof UIColumn) && kid.isRendered()) {
        results.add(kid);
      }
    }
    return (results.iterator());

  }

  /**
   * <p>Return the number of child <code>UIColumn</code> components
   * nested in the specified <code>UIData</code> that have a facet with
   * the specified name.</p>
   *
   * @param data <code>UIData</code> component being analyzed
   * @param name Name of the facet being analyzed
   */
  private int getFacetCount(UIData data, String name) {

    int n = 0;
    Iterator kids = getColumns(data);
    while (kids.hasNext()) {
      UIComponent kid = (UIComponent) kids.next();
      if (kid.getFacet(name) != null) {
        n++;
      }
    }
    return (n);

  }

  protected Iterator getChildren(UIComponent oComponent){
    List oResults = new ArrayList();
    for(Iterator oKids = oComponent.getChildren().iterator(); oKids.hasNext();){
      UIComponent oKid = (UIComponent)oKids.next();
      if(oKid.isRendered())
        oResults.add(oKid);
    }
    return oResults.iterator();
  }

  private void encodeRecursive(FacesContext oContext,UIComponent oComponent) throws IOException{
    if (!oComponent.isRendered()){
      return;  
    }
    oComponent.encodeBegin(oContext);
    if (oComponent.getRendersChildren()){
      oComponent.encodeChildren(oContext); 
    }
    else{
      Iterator oChildren = getChildren(oComponent);
      for(;oChildren.hasNext();){
        UIComponent oChildComponent = (UIComponent)oChildren.next();
        encodeRecursive(oContext,oChildComponent);
      }
    }
    oComponent.encodeEnd(oContext);
  }

  /**
   * <p>Return an array of stylesheet classes to be applied to
   * each column in the table in the order specified. Every column may or
   * may not have a class.</p>
   *
   * @param data {@link UIData} component being rendered
   */
  private String[] getColumnClasses(UIData data) {

    String values = (String) data.getAttributes().get("columnClasses");
    if (values == null) {
      return (new String[0]);
    }
    values = values.trim();
    ArrayList list = new ArrayList();
    while (values.length() > 0) {
      int comma = values.indexOf(",");
      if (comma >= 0) {
        list.add(values.substring(0, comma).trim());
        values = values.substring(comma + 1);
      } else {
        list.add(values.trim());
        values = "";
      }
    }
    
    // now iterate through the columns and remove the class for any
    // columns that aren't rendered
    List columns = data.getChildren();
    int listIndex = 0;
    for (int i=0; i < columns.size(); i++) {
      if (i >= list.size())
        break;
      UIComponent kid = (UIComponent) columns.get(i);
      if ((kid instanceof UIColumn) && !kid.isRendered()) {
        list.remove(listIndex);
      } else {
        listIndex++;
      }
    }
    
    String results[] = new String[list.size()];
    return ((String[]) list.toArray(results));
  }
  
  /**
   * <p>Return an array of stylesheet classes to be applied to
   * each header in the table in the order specified. Every column may or
   * may not have a class.</p>
   *
   * @param data {@link UIData} component being rendered
   */
  private String[] getHeaderClasses(UIData data) {

    String values = (String) data.getAttributes().get("headerClasses");
    if (values == null) {
      return (new String[0]);
    }
    values = values.trim();
    ArrayList list = new ArrayList();
    while (values.length() > 0) {
      int comma = values.indexOf(",");
      if (comma >= 0) {
        list.add(values.substring(0, comma).trim());
        values = values.substring(comma + 1);
      } else {
        list.add(values.trim());
        values = "";
      }
    }
    
    // now iterate through the columns and remove the class for any
    // columns that aren't rendered
    List columns = data.getChildren();
    int listIndex = 0;
    for (int i=0; i < columns.size(); i++) {
      if (i >= list.size())
        break;
      UIComponent kid = (UIComponent) columns.get(i);
      if ((kid instanceof UIColumn) && !kid.isRendered()) {
        list.remove(listIndex);
        
      } else {
        listIndex++;
      }
    }
    
    String results[] = new String[list.size()];
    return ((String[]) list.toArray(results));
  }

  /**
   * <p>Return the number of child <code>UIColumn</code> components
   * that are nested in the specified {@link UIData}.</p>
   *
   * @param data {@link UIData} component being analyzed
   */
  private int getColumnCount(UIData data) {

    int columns = 0;
    Iterator kids = getColumns(data);
    while (kids.hasNext()) {
      UIComponent kid = (UIComponent) kids.next();
      columns++;
    }
    return (columns);

  }

  /**
   * <p>Return an array of stylesheet classes to be applied to
   * each row in the table, in the order specified.  Every row may or
   * may not have a stylesheet.</p>
   *
   * @param data {@link UIData} component being rendered
   */
  private String[] getRowClasses(UIData data) {

    String values = (String) data.getAttributes().get("rowClasses");
    if (values == null) {
      return (new String[0]);
    }
    values = values.trim();
    ArrayList list = new ArrayList();
    while (values.length() > 0) {
      int comma = values.indexOf(",");
      if (comma >= 0) {
        list.add(values.substring(0, comma).trim());
        values = values.substring(comma + 1);
      } else {
        list.add(values.trim());
        values = "";
      }
    }
    String results[] = new String[list.size()];
    return ((String[]) list.toArray(results));

  }
  
  private int getNumDataItemsForToggle(FacesContext context, UIComponent component) {
    int numDataItems = 0;
    ValueBinding gbItemsBinding = component.getValueBinding("value");
    List gbItemList = (List)gbItemsBinding.getValue(context);
    if (gbItemList != null && !gbItemList.isEmpty()) {
      numDataItems = gbItemList.size();
    }
    return numDataItems;
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.