Fusion Middleware Documentation
Advanced Search


Developing Web User Interfaces with Oracle ADF Faces
Close Window

Table of Contents

Show All | Collapse

F Code Samples

This appendix provides the full length code samples referenced from sections throughout this guide.

This appendix includes the following sections:

F.1 Samples for Chapter 4, "Using ADF Faces Client-Side Architecture"

Following are code examples for using ADF Faces architecture

F.1.1 The adf-js-partitions.xml File

The default ADF Faces adf-js-partitions.xml file has partitions that you can override by creating your own partitions file. For more information, see Section 4.9, "JavaScript Library Partitioning." Example F-1 shows the default ADF Faces adf-js-partitions.xml file.

Example F-1 The Default adf-js-partitions.xml File

<?xml version="1.0" encoding="utf-8"?>
 
<partitions xmlns="http://xmlns.oracle.com/adf/faces/partition">
 
  <partition>
    <partition-name>boot</partition-name>
    <feature>AdfBootstrap</feature>
  </partition>
 
  <partition>
    <partition-name>core</partition-name>
 
    <feature>AdfCore</feature>
 
    <!-- Behavioral component super classes -->
    <feature>AdfUIChoose</feature>
    <feature>AdfUICollection</feature>
    <feature>AdfUICommand</feature>
    <feature>AdfUIDialog</feature>
    <feature>AdfUIDocument</feature>
    <feature>AdfUIEditableValue</feature>
    <feature>AdfUIForm</feature>
    <feature>AdfUIGo</feature>
    <feature>AdfUIInput</feature>
    <feature>AdfUIObject</feature>
    <feature>AdfUIOutput</feature>
    <feature>AdfUIPanel</feature>
    <feature>AdfUIPopup</feature>
    <feature>AdfUISelectBoolean</feature>
    <feature>AdfUISelectInput</feature>
    <feature>AdfUISelectOne</feature>
    <feature>AdfUISelectMany</feature>
    <feature>AdfUIShowDetail</feature>
    <feature>AdfUISubform</feature>
    <feature>AdfUIValue</feature>
 
    <!-- These are all so common that we group them with core -->
    <feature>AdfRichDocument</feature>
    <feature>AdfRichForm</feature>
    <feature>AdfRichPopup</feature>
    <feature>AdfRichSubform</feature>
    <feature>AdfRichCommandButton</feature>
    <feature>AdfRichCommandLink</feature>
 
    <!-- 
      Dialog is currently on every page for messaging.  No use
      in putting these in a separate partition.
    -->
    <feature>AdfRichPanelWindow</feature>
    <feature>AdfRichDialog</feature>
 
    <!-- af:showPopupBehavior is so small/common, belongs in core -->
    <feature>AdfShowPopupBehavior</feature>
  </partition>
 
  <partition>
    <partition-name>accordion</partition-name>
    <feature>AdfRichPanelAccordion</feature>
  </partition>
 
  <partition>
    <partition-name>border</partition-name>
    <feature>AdfRichPanelBorderLayout</feature>
  </partition>
 
  <partition>
    <partition-name>box</partition-name>
    <feature>AdfRichPanelBox</feature>
  </partition>
  
  <partition>
    <partition-name>calendar</partition-name>
    <feature>AdfUICalendar</feature>
    <feature>AdfRichCalendar</feature>
    <feature>AdfCalendarDragSource</feature>
    <feature>AdfCalendarDropTarget</feature>
  </partition>
  
  <partition>
    <partition-name>collection</partition-name>
    <feature>AdfUIDecorateCollection</feature>
    <feature>AdfRichPanelCollection</feature>
  </partition>
 
  <partition>
    <partition-name>color</partition-name>
    <feature>AdfRichChooseColor</feature>
    <feature>AdfRichInputColor</feature>
  </partition>
 
  <partition>
    <partition-name>date</partition-name>
    <feature>AdfRichChooseDate</feature>
    <feature>AdfRichInputDate</feature>
  </partition>
 
  <partition>
    <partition-name>declarativeComponent</partition-name>
    <feature>AdfUIInclude</feature>
    <feature>AdfUIDeclarativeComponent</feature>
    <feature>AdfRichDeclarativeComponent</feature>
  </partition>
 
  <partition>
    <partition-name>detail</partition-name>
    <feature>AdfRichShowDetail</feature>
  </partition>
 
  <partition>
    <partition-name>dnd</partition-name>
    <feature>AdfDragAndDrop</feature>
    <feature>AdfCollectionDragSource</feature>
    <feature>AdfStampedDropTarget</feature>
    <feature>AdfCollectionDropTarget</feature>
    <feature>AdfAttributeDragSource</feature>
    <feature>AdfAttributeDropTarget</feature>
    <feature>AdfComponentDragSource</feature>
    <feature>AdfDropTarget</feature>    
  </partition>
  
  <partition>
    <partition-name>detailitem</partition-name>
    <feature>AdfRichShowDetailItem</feature>
  </partition>
 
  <partition>
    <partition-name>file</partition-name>
    <feature>AdfRichInputFile</feature>
  </partition>
 
  <partition>
    <partition-name>form</partition-name>
    <feature>AdfRichPanelFormLayout</feature>
    <feature>AdfRichPanelLabelAndMessage</feature>
  </partition>
 
  <partition>
    <partition-name>format</partition-name>
    <feature>AdfRichOutputFormatted</feature>
  </partition>
 
  <partition>
    <partition-name>frame</partition-name>
    <feature>AdfRichInlineFrame</feature>
  </partition>
 
  <partition>
    <partition-name>header</partition-name>
    <feature>AdfRichPanelHeader</feature>
    <feature>AdfRichShowDetailHeader</feature>
  </partition>
 
  <partition>
    <partition-name>imagelink</partition-name>
    <feature>AdfRichCommandImageLink</feature>
  </partition>
 
  <partition>
    <partition-name>iedit</partition-name>
    <feature>AdfInlineEditing</feature>
  </partition>
 
  <partition>
    <partition-name>input</partition-name>
    <feature>AdfRichInputText</feature>
    <feature>AdfInsertTextBehavior</feature>
  </partition>
 
  <partition>
    <partition-name>label</partition-name>
    <feature>AdfRichOutputLabel</feature>
  </partition>
 
  <partition>
    <partition-name>list</partition-name>
    <feature>AdfRichPanelList</feature>
  </partition>
 
  <partition>
    <partition-name>lov</partition-name>
    <feature>AdfUIInputPopup</feature>
    <feature>AdfRichInputComboboxListOfValues</feature>
    <feature>AdfRichInputListOfValues</feature>
  </partition>
 
  <partition>
    <partition-name>media</partition-name>
    <feature>AdfRichMedia</feature>
  </partition>
 
  <partition>
    <partition-name>message</partition-name>
    <feature>AdfUIMessage</feature>
    <feature>AdfUIMessages</feature>
    <feature>AdfRichMessage</feature>
    <feature>AdfRichMessages</feature>
  </partition>
 
  <partition>
    <partition-name>menu</partition-name>
    <feature>AdfRichCommandMenuItem</feature>
    <feature>AdfRichGoMenuItem</feature>
    <feature>AdfRichMenuBar</feature>
    <feature>AdfRichMenu</feature>
  </partition>
 
  <partition>
    <partition-name>nav</partition-name>
    <feature>AdfUINavigationPath</feature>
    <feature>AdfUINavigationLevel</feature>
    <feature>AdfRichBreadCrumbs</feature>
    <feature>AdfRichCommandNavigationItem</feature>
    <feature>AdfRichNavigationPane</feature>
  </partition>
 
  <partition>
    <partition-name>note</partition-name>
    <feature>AdfRichNoteWindow</feature>
  </partition>
 
  <partition>
    <partition-name>poll</partition-name>
    <feature>AdfUIPoll</feature>
    <feature>AdfRichPoll</feature>
  </partition>
 
  <partition>
    <partition-name>progress</partition-name>
    <feature>AdfUIProgress</feature>
    <feature>AdfRichProgressIndicator</feature>
  </partition>
 
  <partition>
    <partition-name>print</partition-name>
    <feature>AdfShowPrintablePageBehavior</feature>
  </partition>
 
  <partition>
    <partition-name>scrollComponentIntoView</partition-name>
    <feature>AdfScrollComponentIntoViewBehavior</feature>
  </partition>
 
  <partition>
    <partition-name>query</partition-name>
    <feature>AdfUIQuery</feature>
    <feature>AdfRichQuery</feature>
    <feature>AdfRichQuickQuery</feature>
  </partition>
 
  <partition>
    <partition-name>region</partition-name>
    <feature>AdfUIRegion</feature>
    <feature>AdfRichRegion</feature>
  </partition>
 
  <partition>
    <partition-name>reset</partition-name>
    <feature>AdfUIReset</feature>
    <feature>AdfRichResetButton</feature>
  </partition>
 
  <partition>
    <partition-name>rte</partition-name>
    <feature>AdfRichTextEditor</feature>
    <feature>AdfRichTextEditorInsertBehavior</feature>
  </partition>
 
  <partition>
    <partition-name>select</partition-name>
 
    <feature>AdfRichSelectBooleanCheckbox</feature>
    <feature>AdfRichSelectBooleanRadio</feature>
    <feature>AdfRichSelectManyCheckbox</feature>
    <feature>AdfRichSelectOneRadio</feature>
  </partition>
 
  <partition>
    <partition-name>selectmanychoice</partition-name>
    <feature>AdfRichSelectManyChoice</feature>
  </partition>
 
  <partition>
    <partition-name>selectmanylistbox</partition-name>
    <feature>AdfRichSelectManyListbox</feature>
  </partition>
 
  <partition>
    <partition-name>selectonechoice</partition-name>
    <feature>AdfRichSelectOneChoice</feature>
  </partition>
 
  <partition>
    <partition-name>selectonelistbox</partition-name>
    <feature>AdfRichSelectOneListbox</feature>
  </partition>
 
  <partition>
    <partition-name>shuttle</partition-name>
    <feature>AdfUISelectOrder</feature>
    <feature>AdfRichSelectManyShuttle</feature>
    <feature>AdfRichSelectOrderShuttle</feature>
  </partition>
 
  <partition>
    <partition-name>slide</partition-name>
    <feature>AdfRichInputNumberSlider</feature>
    <feature>AdfRichInputRangeSlider</feature>
  </partition>
 
  <partition>
    <partition-name>spin</partition-name>
    <feature>AdfRichInputNumberSpinbox</feature>
  </partition>
 
  <partition>
    <partition-name>status</partition-name>
    <feature>AdfRichStatusIndicator</feature>
  </partition>
 
  <partition>
    <partition-name>stretch</partition-name>
    <feature>AdfRichDecorativeBox</feature>
    <feature>AdfRichPanelSplitter</feature>
    <feature>AdfRichPanelStretchLayout</feature>
    <feature>AdfRichPanelDashboard</feature>
    <feature>AdfPanelDashboardBehavior</feature>
    <feature>AdfDashboardDropTarget</feature>
  </partition>
 
  <partition>
    <partition-name>tabbed</partition-name>
    <feature>AdfUIShowOne</feature>
    <feature>AdfRichPanelTabbed</feature>
  </partition>
 
  <partition>
    <partition-name>table</partition-name>
    <feature>AdfUIIterator</feature>
    <feature>AdfUITable</feature>
    <feature>AdfUITable2</feature>
    <feature>AdfUIColumn</feature>
    <feature>AdfRichColumn</feature>
    <feature>AdfRichTable</feature>
  </partition>
 
  <partition>
    <partition-name>toolbar</partition-name>
    <feature>AdfRichCommandToolbarButton</feature>
    <feature>AdfRichToolbar</feature>
  </partition>
 
  <partition>
    <partition-name>toolbox</partition-name>
    <feature>AdfRichToolbox</feature>
  </partition>
 
  <partition>
    <partition-name>train</partition-name>
    <feature>AdfUIProcess</feature>
    <feature>AdfRichCommandTrainStop</feature>
    <feature>AdfRichTrainButtonBar</feature>
    <feature>AdfRichTrain</feature>
  </partition>
 
  <partition>
    <partition-name>tree</partition-name>
    <feature>AdfUITree</feature>
    <feature>AdfUITreeTable</feature>
    <feature>AdfRichTree</feature>
    <feature>AdfRichTreeTable</feature>
  </partition>
 
  <!--
    Some components which typically do have client-side representation,
    but small enough that we might as well download in a single partition
    in the event that any of these are needed.
  -->
  <partition>
    <partition-name>uncommon</partition-name>
    <feature>AdfRichGoButton</feature>
    <feature>AdfRichIcon</feature>
    <feature>AdfRichImage</feature>
    <feature>AdfRichOutputText</feature>
    <feature>AdfRichPanelGroupLayout</feature>
    <feature>AdfRichSeparator</feature>
    <feature>AdfRichSpacer</feature>
    <feature>AdfRichGoLink</feature>
  </partition>
 
  <partition>
    <partition-name>eum</partition-name>
    <feature>AdfEndUserMonitoring</feature>
  </partition>
 
  <partition>
    <partition-name>ads</partition-name>
    <feature>AdfActiveDataService</feature>
  </partition>
 
  <partition>
    <partition-name>automation</partition-name>
    <feature>AdfAutomationTest</feature>
  </partition>
 
</partitions>

F.2 Sample for Chapter 23, "Using Graph Components"

The following code example creates the Employee class, sample data, and drag and drop methods referenced in Section 23.7.6, "Adding Drag and Drop to Graphs."

Example F-2 dragAndDrop Managed Bean for Graph Drag and Drop Example

public class dragAndDrop {
  private Random m_random = new Random(23);
  // Simple class to represent employee data
  public static class Employee {
    public final String name;
    private int performance;
    private int potential;
    private double salary;
    private double bonus;
    private int experience;
    public Employee(String name, Random r) {
      this.name = name;
      this.performance = r.nextInt(100);
      this.potential = r.nextInt(100);
      this.salary = r.nextInt(100000);
      this.bonus = r.nextInt(50000);
      this.experience = r.nextInt(20);
    }
    // Returns a copy of the employee with a new name
    public Employee(String name, Employee e) {
      this.name = name;
      this.performance = e.performance;
      this.potential = e.potential;
      this.salary = e.salary;
      this.bonus = e.bonus;
      this.experience = e.experience;
    }
    public String getName() {return name;}
    public int getPerformance() { return performance; }
    public int getPotential() { return potential; }
    public void setSalary(double salary) { this.salary = salary; }
    public double getSalary() { return salary; }
    public void setBonus(double bonus) { this.bonus = bonus; }
    public double getBonus() { return bonus; }
    public int getExperience() { return experience; }
  }
  // Returns the employee represented by the selection
  private Employee findEmployee(List<Employee> list, GraphSelection selection) {
    if(!(selection instanceof DataSelection))
      return null;
    List<KeyMap> groupKeys = ((DataSelection)selection).getGroupKeys();
    for(KeyMap groupKey : groupKeys) {
      Set groupKeySet = groupKey.keySet();
      for(Object key : groupKeySet) {
        // Find the employee
        String name = groupKey.get((String)key);
        Employee emp = findEmployee(list, name);
        if(emp != null) {
          return emp;
        }
      }
    }
    return null;
  }
  private Employee findEmployee(List<Employee> list, String name) {
    for(Employee emp : list) {
      if(name.equals(emp.name))
        return emp;
    }
    return null;
  }
  // Converts the list of employees to a bubble data model
  private static DataModel createBubbleDataModel(List<Employee> employees) {
    Object[][] data = new Object[employees.size()*3][1];
    Object[] colLabels = new Object[employees.size()*3];    
    Object[] rowLabels = {"Employees"};    
    for(int i=0; i<employees.size(); i++) {
      Employee emp = employees.get(i);
      data[i*3][0] = emp.performance;
      data[i*3+1][0] = emp.salary;
      data[i*3+2][0] = emp.experience;
      colLabels[i*3] = emp.name;
      colLabels[i*3+1] = emp.name + "1";
      colLabels[i*3+2] = emp.name + "2";
    }
    LocalXMLDataSource dataSource = new LocalXMLDataSource(colLabels, rowLabels, data);
    return new GraphDataModel(dataSource);
  }
  protected List<Employee> m_graphList = this.setEmployeeList();
  public List<Employee> setEmployeeList(){
        List<Employee> em_graphList = new ArrayList<Employee>();
        em_graphList.add(new Employee("Dan", m_random));
        em_graphList.add(new Employee("Ben", m_random));
        em_graphList.add(new Employee("Dave", m_random));
        em_graphList.add(new Employee("Chris", m_random));
        em_graphList.add(new Employee("Frank", m_random));
        em_graphList.add(new Employee("Jill", m_random));
        em_graphList.add(new Employee("Ray", m_random));
      return em_graphList;
  }
  public DataModel getGraphModel() {
    if(m_graphList == null) {
      setEmployeeList();
    }
    return createBubbleDataModel(m_graphList);
  }
  protected List<Employee> m_tableModel = this.setTableModelList();
  public List<Employee> setTableModelList(){
      List<Employee> em_tableModel = new ArrayList<Employee>();
      em_tableModel.add(new Employee("Brad", m_random));
      em_tableModel.add(new Employee("Derrick", m_random));
      em_tableModel.add(new Employee("Matt", m_random));
      return em_tableModel;
  }
  public List getTableModel() {
    if(m_tableModel == null) {
     setTableModelList();
    }
    return m_tableModel;
  }
  public DnDAction fromGraphDropListener(DropEvent event) {
    // Get the ComponentHandle from the transferable
    Transferable transferable = event.getTransferable();
    GraphSelectionSet selectionSet = transferable.getData(GraphSelectionSet.class);
    // Now change each marker based on the DropEvent's proposed action
    DnDAction proposedAction = event.getProposedAction();
   for(GraphSelection selection : selectionSet) {
      Employee emp = findEmployee(m_graphList, selection);
      if(emp == null)
        return DnDAction.NONE;
      if(proposedAction == DnDAction.COPY) {
        m_tableModel.add(new Employee("Copy of " + emp.getName(), emp));  
      }
      else if(proposedAction == DnDAction.LINK) {
        m_tableModel.add(new Employee("Link to " + emp.getName(), emp));  
      }
      else if(proposedAction == DnDAction.MOVE) {
        m_graphList.remove(emp);
        m_tableModel.add(emp);
      }
    }
 RequestContext.getCurrentInstance().addPartialTarget(event.getDragComponent());
        return proposedAction;
  }
  public DnDAction fromTableDropListener(DropEvent event) {
    Transferable transferable = event.getTransferable();
    DataFlavor<RowKeySet> dataFlavor = DataFlavor.getDataFlavor(RowKeySet.class, "fromTable");
    RowKeySet set = transferable.getData(dataFlavor);
    Employee emp = null;
    if(set != null && !set.isEmpty()) {
      int index = (Integer) set.iterator().next();
      emp = m_tableModel.get(index);
    }
    if(emp == null)
        return DnDAction.NONE;
    DnDAction proposedAction = event.getProposedAction();
    if(proposedAction == DnDAction.COPY) {
      m_graphList.add(emp);  
    }
    else if(proposedAction == DnDAction.LINK) {
      m_graphList.add(emp);
    }
    else if(proposedAction == DnDAction.MOVE) {
      m_graphList.add(emp);
      m_tableModel.remove(emp);
    }
    else
        return DnDAction.NONE;
   RequestContext.getCurrentInstance().addPartialTarget(event.getDragComponent());
    return event.getProposedAction();
  }

F.3 Samples for Chapter 30, "Using Treemap and Sunburst Components"

Following are code examples for creating treemap and sunburst components.

F.3.1 Sample Code for Treemap and Sunburst Census Data Example

When you create a treemap or sunburst using UI-first development, you can use Java classes and managed beans to define the tree node and tree model, populate the tree with data and add additional methods as needed to configure the treemap or sunburst.

Example F-3 shows a code sample defining the tree node in the census data example. Note that the required settings for label, size, and color are passed in as parameters to the tree node.

Example F-3 Code Sample to Create a Treemap or Sunburst Tree Node

import java.awt.Color;
import java.util.ArrayList;
import java.util.List;
 
public class TreeNode {
  private final String m_text;
  private final Number m_size;
  private final Color m_color;
  private final List<TreeNode> m_children = new ArrayList<TreeNode>();
  
  public TreeNode(String text, Number size, Color color) {
    m_text = text;
    m_size = size;
    m_color = color;
  }
  public String getText() {
    return m_text;
  }
  public Number getSize() {
    return m_size;
  }
  public Color getColor() {
    return m_color;
  }
  public void addChild(TreeNode child) {
    m_children.add(child);
  }
  public void addChildren(List<TreeNode> children) {
    m_children.addAll(children);
  }
  public List<TreeNode> getChildren() {
    return m_children;
  }
  @Override
  public String toString() {
    return m_text + ": " + m_color + " " + Math.round(m_size.doubleValue());
  }
}

To supply data to the treemap or sunburst in UI-first development, add a class or managed bean to your application that extends the tree node in Example F-3 and populates it with data. The class to set up the tree model must be an implementation of the org.apache.myfaces.trinidad.model.TreeModel class. Once the tree model is defined, create a method that implements the org.apache.myfaces.trinidad.model.ChildPropertyTreeModel to complete the tree model.

Example F-4 shows a sample class that sets up the root and child node structure, populates the child levels with data and defines the color and node sizes in the census data example.

Example F-4 Code Sample Creating Census Data Model for Treemap and Sunburst

import java.awt.Color;
 
import java.util.ArrayList;
import java.util.List;
 
import org.apache.myfaces.trinidad.model.ChildPropertyTreeModel;
import org.apache.myfaces.trinidad.model.TreeModel;
 
 
public class CensusData {
 
  public static TreeModel getUnitedStatesData() {
    return getModel(ROOT);
  }
 
  public static TreeModel getRegionWestData() {
    return getModel(REGION_W);
  }
 
  public static TreeModel getRegionNortheastData() {
    return getModel(REGION_NE);
  }
 
  public static TreeModel getRegionMidwestData() {
    return getModel(REGION_MW);
  }
 
  public static TreeModel getRegionSouthData() {
    return getModel(REGION_S);
  }
 
  public static TreeModel getDivisionPacificData() {
    return getModel(DIVISION_P);
  }
 
  private static TreeModel getModel(DataItem rootItem) {
    TreeNode root = getTreeNode(rootItem);
    return new ChildPropertyTreeModel(root, "children");
  }
 
  private static TreeNode getTreeNode(DataItem dataItem)
  {
    // Create the node itself
    TreeNode node = new CensusTreeNode(dataItem.getName(),
                        dataItem.getPopulation(),
                        getColor(dataItem.getIncome(), MIN_INCOME, MAX_INCOME),
                        dataItem.getIncome());
 
    // Create its children
    List<TreeNode> children = new ArrayList<TreeNode>();
    for(DataItem childItem : dataItem.children) {
      children.add(getTreeNode(childItem));
    }
 
    // Add the children and return
    node.addChildren(children);
    return node;
  }
 
  private static Color getColor(double value, double min, double max) {
    double percent = Math.max((value - min) / max, 0);
    if(percent > 0.5) {
      double modifier = (percent - 0.5) * 2;
      return new Color((int)(modifier*102), (int)(modifier*153), (int)(modifier*51));
    }
    else {
      double modifier = percent *2;
      return new Color((int)(modifier*204), (int)(modifier*51), 0);
    }
  }
 
  public static class DataItem {
    private final String name;
    private final int population;
    private final int income;
    private final List<DataItem> children;
 
    public DataItem(String name, int population, int income) {
      this.name = name;
      this.population = population;
      this.income = income;
      this.children = new ArrayList<DataItem>();
    }
 
    public void addChild(DataItem child) {
      this.children.add(child);
    }
 
    public String getName() {
      return name;
    }
 
    public int getPopulation() {
      return population;
    }
 
    public int getIncome() {
      return income;
    }
 
    public List<CensusData.DataItem> getChildren() {
      return children;
    }
  }
 
  private static final int MIN_INCOME = 0;
  private static final int MAX_INCOME = 70000;
 
  private static final DataItem ROOT = new DataItem("United States", 301461533, 51425);
 
  private static final DataItem REGION_NE = new DataItem("Northeast Region", 54906297, 57208);
  private static final DataItem REGION_MW = new DataItem("Midwest Region", 66336038, 49932);
  private static final DataItem REGION_S = new DataItem("South Region", 110450832, 47204);
  private static final DataItem REGION_W = new DataItem("West Region", 69768366, 56171);
 
  private static final DataItem DIVISION_NE = new DataItem("New England", 14315257, 61511);
  private static final DataItem DIVISION_MA = new DataItem("Middle Atlantic", 40591040, 55726);
  private static final DataItem DIVISION_ENC = new DataItem("East North Central", 46277998, 50156);
  private static final DataItem DIVISION_WNC = new DataItem("West North Central", 20058040, 49443);
  private static final DataItem DIVISION_SA = new DataItem("South Atlantic", 57805475, 50188);
  private static final DataItem DIVISION_ESC = new DataItem("East South Central", 17966553, 41130);
  private static final DataItem DIVISION_WSC = new DataItem("West South Central", 34678804, 45608);
  private static final DataItem DIVISION_M = new DataItem("Mountain", 21303294, 51504);
  private static final DataItem DIVISION_P = new DataItem("Pacific", 48465072, 58735);
 
  static {
    // Set up the regions
    ROOT.addChild(REGION_NE);
    ROOT.addChild(REGION_MW);
    ROOT.addChild(REGION_S);
    ROOT.addChild(REGION_W);
 
    // Set up the divisions
    REGION_NE.addChild(DIVISION_NE);
    REGION_NE.addChild(DIVISION_MA);
    REGION_MW.addChild(DIVISION_ENC);
    REGION_MW.addChild(DIVISION_WNC);
    REGION_S.addChild(DIVISION_SA);
    REGION_S.addChild(DIVISION_ESC);
    REGION_S.addChild(DIVISION_WSC);
    REGION_W.addChild(DIVISION_M);
    REGION_W.addChild(DIVISION_P);
 
    // Set up the states
    DIVISION_NE.addChild(new DataItem("Connecticut", 3494487, 67721));
    DIVISION_NE.addChild(new DataItem("Maine", 1316380, 46541));
    DIVISION_NE.addChild(new DataItem("Massachusetts", 6511176, 64496));
    DIVISION_NE.addChild(new DataItem("New Hampshire", 1315419, 63033));
    DIVISION_NE.addChild(new DataItem("Rhode Island", 1057381, 55569));
    DIVISION_NE.addChild(new DataItem("Vermont", 620414, 51284));
 
    DIVISION_MA.addChild(new DataItem("New Jersey", 8650548, 68981));
    DIVISION_MA.addChild(new DataItem("New York", 19423896, 55233));
    DIVISION_MA.addChild(new DataItem("Pennsylvania", 12516596, 49737));
 
    DIVISION_ENC.addChild(new DataItem("Indiana", 6342469, 47465));
    DIVISION_ENC.addChild(new DataItem("Illinois", 12785043, 55222));
    DIVISION_ENC.addChild(new DataItem("Michigan", 10039208, 48700));
    DIVISION_ENC.addChild(new DataItem("Ohio", 11511858, 47144));
    DIVISION_ENC.addChild(new DataItem("Wisconsin", 5599420, 51569));
 
    DIVISION_WNC.addChild(new DataItem("Iowa", 2978880, 48052));
    DIVISION_WNC.addChild(new DataItem("Kansas", 2777835, 48394));
    DIVISION_WNC.addChild(new DataItem("Minnesota", 5188581, 57007));
    DIVISION_WNC.addChild(new DataItem("Missouri", 5904382, 46005));
    DIVISION_WNC.addChild(new DataItem("Nebraska", 1772124, 47995));
    DIVISION_WNC.addChild(new DataItem("North Dakota", 639725, 45140));
    DIVISION_WNC.addChild(new DataItem("South Dakota", 796513, 44828));
 
    DIVISION_SA.addChild(new DataItem("Delaware", 863832, 57618));
    DIVISION_SA.addChild(new DataItem("District of Columbia", 588433, 56519));
    DIVISION_SA.addChild(new DataItem("Florida", 18222420, 47450));
    DIVISION_SA.addChild(new DataItem("Georgia", 9497667, 49466));
    DIVISION_SA.addChild(new DataItem("Maryland", 5637418, 69475));
    DIVISION_SA.addChild(new DataItem("North Carolina", 9045705, 45069));
    DIVISION_SA.addChild(new DataItem("South Carolina", 4416867, 43572));
    DIVISION_SA.addChild(new DataItem("Virginia", 7721730, 60316));
    DIVISION_SA.addChild(new DataItem("West Virginia", 1811403, 37356));
 
    DIVISION_ESC.addChild(new DataItem("Alabama", 4633360, 41216));
    DIVISION_ESC.addChild(new DataItem("Kentucky", 4252000, 41197));
    DIVISION_ESC.addChild(new DataItem("Mississippi", 2922240, 36796));
    DIVISION_ESC.addChild(new DataItem("Tennessee", 6158953, 42943));
 
    DIVISION_WSC.addChild(new DataItem("Arkansas", 2838143, 38542));
    DIVISION_WSC.addChild(new DataItem("Louisiana", 4411546, 42167));
    DIVISION_WSC.addChild(new DataItem("Oklahoma", 3610073, 41861));
    DIVISION_WSC.addChild(new DataItem("Texas", 23819042, 48199));
 
    DIVISION_M.addChild(new DataItem("Arizona", 6324865, 50296));
    DIVISION_M.addChild(new DataItem("Colorado", 4843211, 56222));
    DIVISION_M.addChild(new DataItem("Idaho", 1492573, 46183));
    DIVISION_M.addChild(new DataItem("Montana", 956257, 43089));
    DIVISION_M.addChild(new DataItem("Nevada", 2545763, 55585));
    DIVISION_M.addChild(new DataItem("New Mexico", 1964860, 42742));
    DIVISION_M.addChild(new DataItem("Utah", 2651816, 55642));
    DIVISION_M.addChild(new DataItem("Wyoming", 523949, 51990));
 
    DIVISION_P.addChild(new DataItem("Alaska", 683142, 64635));
    DIVISION_P.addChild(new DataItem("California", 36308527, 60392));
    DIVISION_P.addChild(new DataItem("Hawaii", 1280241, 64661));
    DIVISION_P.addChild(new DataItem("Oregon", 3727407, 49033));
    DIVISION_P.addChild(new DataItem("Washington", 6465755, 56384));
  }
 
  public static class CensusTreeNode extends TreeNode {
    private int income;
 
    public CensusTreeNode(String text, Number size, Color color, int income) {
      super(text, size, color);
      this.income = income;
    }
 
    public int getIncome() {
      return income;
    }
  }
}

Finally, to complete the tree model in UI-first development, add a managed bean to your application that references the class or bean that contains the data and, optionally, add any other methods to customize the treemap or sunburst.

Example F-5 shows a code sample that will instantiate the census treemap and populate it with census data. The example also includes a sample method (convertToString) that will convert the treemap node's row data to a string for label display.

Example F-5 Managed Bean Example to Set Census Data Treemap

import org.apache.myfaces.trinidad.component.UIXHierarchy;
import org.apache.myfaces.trinidad.model.RowKeySet;
import org.apache.myfaces.trinidad.model.TreeModel;
import oracle.adf.view.faces.bi.component.treemap.UITreemap;
 
public class SampleTreemap {
  // Data Model Attrs
  private TreeModel currentModel;
  private final CensusData censusData = new CensusData();
  private String censusRoot = "United States";
  private UITreemap treemap;
 
  public TreeModel getCensusRootData() {
    return censusData.getUnitedStatesData();
  }
  public TreeModel getCensusData() {
    if ("West Region".equals(censusRoot))
      return censusData.getRegionWestData();
    else if ("South Region".equals(censusRoot))
      return censusData.getRegionSouthData();
    else if ("Midwest Region".equals(censusRoot))
      return censusData.getRegionMidwestData();
    else if ("Northeast Region".equals(censusRoot))
      return censusData.getRegionNortheastData();
    else if ("Pacific Division".equals(censusRoot))
      return censusData.getDivisionPacificData();
    else
      return censusData.getUnitedStatesData();
  }
  public TreeModel getData() {
    // Return cached data model if available
    if(currentModel != null)
      return currentModel;
    currentModel = getCensusData();
    return currentModel;
  }
  public void setCensusRoot(String censusRoot) {
    this.censusRoot = censusRoot;
  }
  public String getCensusRoot() {
    return censusRoot;
  }
  //Converts the rowKeySet into a string of node text labels.
  public static String convertToString(RowKeySet rowKeySet, UIXHierarchy hierarchy) {
    StringBuilder s = new StringBuilder();
    if (rowKeySet != null) {
      for (Object rowKey : rowKeySet) {
        TreeNode rowData = (TreeNode)hierarchy.getRowData(rowKey);
        s.append(rowData.getText()).append(", ");
      }
      // Remove the trailing comma
      if (s.length() > 0)
        s.setLength(s.length() - 2);
    }
    return s.toString();
  }
  public void setTreemap(UITreemap treemap) {
        this.treemap = treemap;
  }
  public UITreemap getTreemap() {
        return treemap;
  }
}

The code to set up the sunburst census sample is nearly identical since both components use the same tree model. See Section F.3.2, "Code Sample for Sunburst Managed Bean" for an example.

F.3.2 Code Sample for Sunburst Managed Bean

The following code sample instantiates the census sunburst and populates it with census data. The example also includes a sample method (convertToString) that will convert the sunburst node's row data to a string for label display.

Example F-6 Managed Bean Example to Set Census Data Sunburst

import oracle.adf.view.faces.bi.component.sunburst.UISunburst;
import org.apache.myfaces.trinidad.component.UIXHierarchy;
import org.apache.myfaces.trinidad.model.RowKeySet;
import org.apache.myfaces.trinidad.model.TreeModel;
 
public class SunburstSample {
  // Components
  private UISunburst sunburst;
  // Attributes
  private TreeModel currentModel;
  private final CensusData censusData = new CensusData();
  private String censusRoot = "United States";
  
  public TreeModel getCensusRootData() {
    return censusData.getUnitedStatesData();
  }
  public TreeModel getCensusData() {
    if ("West Region".equals(censusRoot))
      return censusData.getRegionWestData();
    else if ("South Region".equals(censusRoot))
      return censusData.getRegionSouthData();
    else if ("Midwest Region".equals(censusRoot))
      return censusData.getRegionMidwestData();
    else if ("Northeast Region".equals(censusRoot))
      return censusData.getRegionNortheastData();
    else if ("Pacific Division".equals(censusRoot))
      return censusData.getDivisionPacificData();
    else
      return censusData.getUnitedStatesData();
  }
  public TreeModel getData() {
    // Return cached data model if available
    if(currentModel != null)
      return currentModel;
    currentModel = getCensusData();
    return currentModel;
  }
  public void setCensusRoot(String censusRoot) {
    this.censusRoot = censusRoot;
  }
  public String getCensusRoot() {
    return censusRoot;
  }
  public static String convertToString(RowKeySet rowKeySet, UIXHierarchy hierarchy) {
    StringBuilder s = new StringBuilder();
    if (rowKeySet != null) {
      for (Object rowKey : rowKeySet) {
        TreeNode rowData = (TreeNode)hierarchy.getRowData(rowKey);
        s.append(rowData.getText()).append(", ");
      }
      // Remove the trailing comma
      if (s.length() > 0)
        s.setLength(s.length() - 2);
    }
    return s.toString();
  }  
  public void setSunburst(UISunburst sunburst) {    
    this.sunburst = sunburst;
  }
  public UISunburst getSunburst() {
    return sunburst;
  }
}

F.4 Samples for Chapter 34, "Creating Custom ADF Faces Components"

Following are code examples for creating a custom component.

F.4.1 Event Code for JavaScript

When you create a custom component, you need to provide code in JavaScript that will perform the functions required when a event is fired, such as a mouse click. Example F-7 shows the event code that might be added for the tagPane component.

Example F-7 tagPane Event JavaScript

/**
 * Fires a select type event to the server for the source component 
* when a tag is clicked. 
*/
function AcmeTagSelectEvent(source, tag)
{
 AdfAssert.assertPrototype(source, AdfUIComponent);
 AdfAssert.assertString(tag); this.Init(source, tag);
}
// make AcmeTagSelectEvent a subclass of AdfComponentEvent

AdfObject.createSubclass(AcmeTagSelectEvent, AdfComponentEvent);
/**
 * The event type 
*/
AcmeTagSelectEvent.SELECT_EVENT_TYPE = "tagSelect";
/**
 * Event Object constructor 
*/
AcmeTagSelectEvent.prototype.Init = function(source, tag)
{
  AdfAssert.assertPrototype(source, AdfUIComponent);
  AdfAssert.assertString(tag);
  this._tag = tag;
 AcmeTagSelectEvent.superclass.Init.call(this, source, AcmeTagSelectEvent.SELECT_EVENT_TYPE);}
/**
 * Indicates this event should be sent to the server 
*/
AcmeTagSelectEvent.prototype.propagatesToServer = function()
{ 
  return true;
}
/**
 * Override of AddMarshalledProperties to add parameters * sent server side. 
*/
AcmeTagSelectEvent.prototype.AddMarshalledProperties = function( properties) 
{ 
  properties.tag = this._tag;


 }
/**
 * Convenient method for queue a AcmeTagSelectEvent.
 */
AcmeTagSelectEvent.queue = function(component, tag)
{  
AdfAssert.assertPrototype(component, AdfUIComponent);
 AdfAssert.assertString(tag);
 AdfLogger.LOGGER.logMessage(AdfLogger.FINEST,     "AcmeTagSelectEvent.queue(component, tag)");
 new AcmeTagSelectEvent(component, tag).queue(true);
}
/**
 * returns the selected file type 
*/
AcmeTagSelectEvent.prototype.getTag = function()
{
  return this._tag;}
/**
 * returns a debug string 
*/
AcmeTagSelectEvent.prototype.toDebugString = function()
{ 
 var superString = AcmeTagSelectEvent.superclass.toDebugString.call(this);
 return superString.substring(0, superString.length - 1)
  +     ", tag=" 
  + this._tag     + "]";
}
/*
*
* Make sure that this event only invokes immediate validators 
* on the client. 
*/
AcmeTagSelectEvent.prototype.isImmediate = function()
{ 
  return true;
}

F.4.2 Example Tag Library Descriptor File Code

When you create a custom component, you need to create a tag library descriptor (TLD) file, which provides more information on the Java Class to the JSP compilation engine and IDE tools. Example F-8 shows an example TLD file that defines the tagPane component.

Example F-8 tagPane acme.tld Tag Library Descriptor Code

<?xml version = '1.0' encoding = 'windows-1252'?>
<taglib xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
     http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd"
     version="2.1" xmlns="http://java.sun.com/xml/ns/javaee">
 <description>Acme Corporation JSF components</description>
 <display-name>acme</display-name>
 <tlib-version>1.0</tlib-version>
 <short-name>acme</short-name>
 <uri>http://oracle.adfdemo.acme</uri>
  <tag>
  <description>
  </description>
  <name>tagPane</name>
  <tag-class>oracle.adfdemo.acme.faces.taglib.TagPaneTag</tag-class>
  <body-content>JSP</body-content>
  <attribute>
   <name>id</name>
   <rtexprvalue>true</rtexprvalue>
  </attribute>
  <attribute>
   <name>rendered</name>
   <deferred-value>
    <type>boolean</type>
   </deferred-value>
  </attribute>
  <attribute>
   <name>tagSelectListener</name>
   <deferred-method>
    <method-signature>void
    </method-signature>
        myMethod(oracle.adfdemo.acme.faces.event.TagSelectEvent)
   </deferred-method>
  </attribute>
  <attribute>
   <name>visible</name>
   <deferred-value>
    <type>boolean</type>
   </deferred-value>
  </attribute>
  <attribute>
   <name>partialTriggers</name>
   <deferred-value>
   </deferred-value>
  </attribute>
  <attribute>
   <name>inlineStyle</name>
   <deferred-value/>
  </attribute>
  <attribute>
   <name>inlineClass</name>
   <deferred-value/>
  </attribute>
  <attribute>
   <name>tags</name>
   <deferred-value/>
  </attribute>
  <attribute>
   <name>binding</name>
   <deferred-value/>
  </attribute>
  <attribute>
   <name>orderBy</name>
   <deferred-value/>
  </attribute>
 </tag>
</taglib>

F.4.3 Example Component Class Code

When you create a custom component, you need to create a Java class that contains property information and accessors. Example F-9 shows the code used to create the example TagPane component.

Example F-9 TagPane Component Class

package oracle.adfdemo.acme.faces.component;
 
import java.util.Map;
import java.util.Set;
 
import javax.el.MethodExpression;
 
import javax.faces.event.AbortProcessingException;
import javax.faces.event.FacesEvent;
 
import oracle.adf.view.rich.event.ClientListenerSet;
 
import oracle.adfdemo.acme.faces.event.TagSelectEvent;
import oracle.adfdemo.acme.faces.event.TagSelectListener;
 
import org.apache.myfaces.trinidad.bean.FacesBean;
import org.apache.myfaces.trinidad.bean.PropertyKey;
import org.apache.myfaces.trinidad.component.UIXObject;
 
public class TagPane
  extends UIXObject
{
 
  /**
  * <p>Establishes a <code>Type</code> bean that contains JSF component property
  * information.  This static public final property <code>TYPE</code> shadows a
  * property with the same name in the super class.  The <code>TYPE</code>
  * attribute is defined once pre JSF component class.  The factory method call to
  * <code>FacesBean.Type</code> passes the super class reference
  * <code>UIXObject.TYPE</code> which copies down property information defined in
  * the super type.</p>
   */
  static public final FacesBean.Type TYPE =
    new FacesBean.Type(UIXObject.TYPE);
 
  /**
   * <p>Custom CSS applied to the style attribute of the root markup node.</p>
   */
  static public final PropertyKey INLINE_STYLE_KEY =
    TYPE.registerKey("inlineStyle", String.class);
 
  /**
   * <p>Custom CSS class to the class attribute of the root markup node.</p>
   */
  static public final PropertyKey STYLE_CLASS_KEY =
    TYPE.registerKey("styleClass", String.class);
 
  /**
   * <p>Key used to identify the <code>visible</code> property that
   * is of type <code>Boolean.class</code>.</p>
   */
  static public final PropertyKey VISIBLE_KEY =
    TYPE.registerKey("visible", Boolean.class, Boolean.TRUE);
 
 
  /**
   * <p>Key used to identify the <code>partialTriggers</code> property that
   * is of type <code>String[].class</code>.</p>
   */
  static public final PropertyKey PARTIAL_TRIGGERS_KEY =
    TYPE.registerKey("partialTriggers", String[].class);
 
 
  /**
   * <p>Key used to identify the <code>tagSelectListener</code> property that
   * is of type <code>MethodExpression.class</code>.</p>
   */
  static public final PropertyKey TAG_SELECT_LISTENER_KEY =
    TYPE.registerKey("tagSelectListener", MethodExpression.class);
 
  /**
   * <p>Key used to identity the <code>clientComponent</code> flag that
   * is of type <code>Boolean.class</code>.</p>
   */
  static public final PropertyKey CLIENT_COMPONENT_KEY =
    TYPE.registerKey("clientComponent", Boolean.class);
 
 
  /**
   * <p>Key use to identity the <code>clientListeners</code> property
   * that is a collection class of <code>ClientListenerSet.class</code>.</p>
   */
  static public final PropertyKey CLIENT_LISTENERS_KEY =
    TYPE.registerKey("clientListeners", ClientListenerSet.class,
                     PropertyKey.CAP_NOT_BOUND);
 
  /**
   * <p>Key used to identify the <code>clientAttributes</code> property this
   * is a set of type <code>PropertyKey.CAP_NOT_BOUND</code>.</p>
   */
  static public final PropertyKey CLIENT_ATTRIBUTES_KEY =
    TYPE.registerKey("clientAttributes", Set.class,
                     PropertyKey.CAP_NOT_BOUND);
 
  /**
   * <p>Key used to identify the <code>tags</code> property that
   * is of type <code>Map.class</code>.</p>
   */
  static public final PropertyKey TAGS_KEY =
    TYPE.registerKey("tags", Map.class);
 
 
  /**
   * <p>Key used to identify the <code>orderBy</code> property that
   * is of type <code>String.class</code>.</p>
   */
  static public final PropertyKey ORDER_BY_KEY =
    TYPE.registerKey("orderBy", String.class);
 
  /**
   * <p>The constructor calls the super classes overloaded constructor passing
   * the <code>rendererType</code>.
   */
  public TagPane()
  {
    // Pass the renderer type to the super class.
    super(RENDERER_TYPE);
 
    // requires a client component by default
    setBooleanProperty(CLIENT_COMPONENT_KEY, Boolean.TRUE);
  }
 
 
  /**
   * @param newpartialTriggers array of render dependent client ids
   */
  public void setPartialTriggers(String[] newpartialTriggers)
  {
    setProperty(PARTIAL_TRIGGERS_KEY, newpartialTriggers);
  }
 
  /**
   * @return array of render dependent client ids
   */
  public String[] getPartialTriggers()
  {
    return (String[]) getProperty(PARTIAL_TRIGGERS_KEY);
  }
 
 
  /**
   * <p>Sets client listeners that provide specialized behaviors such as
   * drag-and-drop.
   * You can subscribe to any client event using the event type and method.
   * For example, we could add a client listener for our custom client event
   * <code>oracle.adfdemo.acme.js.event.TagSelectEvent</code>.
   * </p>
   * <pre>
   *     &lt;acme:tagPane tags="#{bean.tags}"&gt;
   *         &lt;clientListener type="tagSelect" method="onClickType" /&gt;
   *     &lt;\acme:tagPane&gt;
   * </pre>
   *
   * <p>In the fragment above, the method "onClickType" is a JavaScript function that
   * has a single event parameter.</p>
   *
   * <per>
   *    function onClickType(event) {
   *       alter("You clicked on tag: " + event.getTag());
   *    }
   * </per>
   *
   * @param newclientListeners  client listener collection
   */
  public void setClientListeners(ClientListenerSet newclientListeners)
  {
    setProperty(CLIENT_LISTENERS_KEY, newclientListeners);
  }
 
  /**
   * <p>Returns client listeners that provide specialized behaviors such as
   * drag-and-drop.</p>
   *
   * @return client listener set
   */
  public ClientListenerSet getClientListeners()
  {
    return (ClientListenerSet) getProperty(CLIENT_LISTENERS_KEY);
  }
 
  /**
   * <p>Sets attributes on the client component,
   * <code>oracle.adfdemo.acme.js.event.AcmeTagPane.js</code> that can be used by
   * <code>ClientListners</code>.  The state is actually managed by the
   * component.  This collection is a <code>Set</code> of client attribute names
   * that are also server component properties.
   * <br/><br/>
   * Client attributes must be set using the <code>setClientAttribute</code> JSP tag.
   * Consider the following:
   * <pre>
   *     &lt;acme:tagPane targetFolder="somefolder"&gt;
   *         &lt;clientListener type="tagSelect" method="onClickType" /&gt;
   *         &lt;clientAttribute name="whoareyou" method="While E. Coyote" /&gt;
   *     &lt;\acme:tagPane&gt;
   * </pre>
   *
   * <p>In the fragment above, the method "onClickType" is a JavaScript function that
   * has a single event parameter.</p>
   *
   * <per>
   *    function onClickType(event) {
   *       alter(event.getSource().getProperty("whoareyou")
   *           + " clicked on tag: " + event.getTag());
   *    }
   * </per>
   *
   * @param newclientAttributes a set of client attribute names
   */
  public void setClientAttributes(Set newclientAttributes)
  {
    setProperty(CLIENT_ATTRIBUTES_KEY, newclientAttributes);
  }
 
  /**
   * <p><code>Set</code> of client component attribute names.  The state
   * is also kept in the server side component's <code>attributes</code> Map.</p>
   *
   * @return colleciton of unique client component attribute names
   */
  public Set getClientAttributes()
  {
    return (Set) getProperty(CLIENT_ATTRIBUTES_KEY);
  }
 
  /**
   * <p>Sets the <code>newselectListener</code> method binding
   * expression that expects a single parameter of type {@link
   * oracle.adfdemo.acme.faces.event.TagSelectEvent}.
   * This binding will be when the client-side
   * <code>oracle.adfdemo.acme.js.event.AcmeTagSelectEvent.js</code>
   * is queued from clicking on one of the <code>tag</code>s.</p>
   *
   * @param newselectListener invokes a {@link oracle.adfdemo.acme.faces.event.TagSelectEvent} method expression
   */
  public void setTagSelectListener(MethodExpression newselectListener)
  {
    setProperty(TAG_SELECT_LISTENER_KEY, newselectListener);
  }
 
  /**
   * <p>Returns a method binding expression that is fired when the client-side
   * <code>oracle.adfdemo.acme.js.event.AcmeTagSelectEvent.js</code> is
   * queued.</p>
   *
   * @return invokes a {@link oracle.adfdemo.acme.faces.event.TagSelectEvent}
   * method expression
   */
  public MethodExpression getTagSelectListener()
  {
    return (MethodExpression) getProperty(TAG_SELECT_LISTENER_KEY);
  }
 
  /**
   * <p>Method for adding a listener implementing {@link
   * oracle.adfdemo.acme.faces.event.TagSelectListener}.</p>
   *
   * @param listener tag select listener
   */
  public void addTagSelectListener(TagSelectListener listener)
  {
    addFacesListener(listener);
  }
 
  /**
   * <p>Removes a {@link oracle.adfdemo.acme.faces.event.TagSelectListener}
   * listener.</p>
   *
   * @param listener tag select listener
   */
  final public void removeSelectListener(TagSelectListener listener)
  {
    removeFacesListener(listener);
  }
 
  /**
   * <p>Returns an array of attached {@link
   * oracle.adfdemo.acme.faces.event.TagSelectListener} listeners.</p>
   *
   * @return  an array of attached select listeners.
   */
  final public TagSelectListener[] getSelectListeners()
  {
    return (TagSelectListener[]) getFacesListeners(TagSelectListener.class);
  }
 
 
  /**
   * <p>Exposes the <code>FacesBean.Type</code> for this class through a protected
   * method.  This method is called but the <code>UIComponentBase</code> super
   * class to setup the components <code>ValueMap</code> which is the container
   * for the <code>attributes</code> colleciton.</p>
   *
   * @return <code>FolderSummary.TYPE</code> static property
   */
  @Override
  protected FacesBean.Type getBeanType()
  {
    return TYPE;
  }
 
  /**
   * <p>
   * </p>
   *
   * @param facesEvent faces event
   * @throws AbortProcessingException exception during processing
   */
  @Override
  public void broadcast(FacesEvent facesEvent)
    throws AbortProcessingException
  {
 
    // notify the bound TagSelectListener
    if (facesEvent instanceof TagSelectEvent)
    {
      TagSelectEvent event = (TagSelectEvent) facesEvent;
 
      // utility method found in UIXComponentBase for invoking method event
      // expressions
      broadcastToMethodExpression(event, getTagSelectListener());
    }
 
    super.broadcast(facesEvent);
  }
 
  /**
   * <p>CSS value applied to the root component's style attribute.</p>
   *
   * @param newinlineStyle CSS custom style text
   */
  public void setInlineStyle(String newinlineStyle)
  {
    // inlineStyle = newinlineStyle;
    setProperty(INLINE_STYLE_KEY, newinlineStyle);
  }
 
  /**
   * <p>CSS value applied to the root component's style attribute.</p>
   *
   * @return newinlineStyle CSS custom style text
   */
  public String getInlineStyle()
  {
    // return inlineStyle;
    return (String) getProperty(INLINE_STYLE_KEY);
  }
 
  /**
   * <p>CSS style class added to the components class attribute.</p>
   * @param newstyleClass custom class style attribute
   */
  public void setStyleClass(String newstyleClass)
  {
    setProperty(STYLE_CLASS_KEY, newstyleClass);
  }
 
  /**
   * <p>CSS style class added to the components class attribute.</p>
   * @return newstyleClass custom class style attribute
   */
  public String getStyleClass()
  {
    return (String) getProperty(STYLE_CLASS_KEY);
  }
 
  /**
   * <p>Sets the visibility of the component.  The visibility
   * is not the same as <code>rendered</code>.  The <code>visible</code>
   * attribute effects the CSS style on the CSS root of the component.
   * </p>
   *
   * @param newvisible <code>true</code> if the markup is not hidden in the
   * browser
   */
  public void setVisible(boolean newvisible)
  {
    setBooleanProperty(VISIBLE_KEY, newvisible);
  }
 
  /**
   * <p>Returns the visibility of the component.  The visibility
   * is not the same as <code>rendered</code>.  The <code>visible</code>
   * attribute effects the CSS style on the CSS root of the component.
   * </p>
   *
   * @return <code>true</code> if the markup is not hidden in the browser
   */
  public boolean isVisible()
  {
    return getBooleanProperty(VISIBLE_KEY, Boolean.TRUE);
  }
 
  /**
   * <p>This component's type, <code>oracle.adfdemo.acme.TagPane</code></p>
   */
  static public final String COMPONENT_TYPE =
    "oracle.adfdemo.acme.TagPane";
 
  /**
   * <p>Logical name given to the registered renderer for this component.</p>
   */
  static public final String RENDERER_TYPE = "oracle.adfdemo.acme.TagPane";
 
  /**
   * <p>Sets a Map of weighted tags.  The key represents the tag name
   * and the value a number.</p>
   *
   * @param newtags tags to be rendered
   */
  public void setTags(Map<String, Number> newtags)
  {
    setProperty(TAGS_KEY, newtags);
  }
 
  /**
   * <p>Gets a Map of weighted tags.  The key represents the tag name
   * and the value a number.</p>
   *
   * @return newtags tags to be rendered
   */
  public Map<String, Number> getTags()
  {
    return (Map<String, Number>) getProperty(TAGS_KEY);
  }
 
  /**
   * <p>Sets the order that the tags are rendered.
   * The valid enumerations are "alpha" and "weight".</p>
   *
   * @param neworderBy order by enumeration
   */
  public void setOrderBy(String neworderBy)
  {
    setProperty(ORDER_BY_KEY, neworderBy);
  }
 
  /**
   * <p>Gets the order that the tags are rendered.
   * The valid enumerations are "alpha" and "weight".</p>
   *
   * @return order by enumeration
   */
  public String getOrderBy()
  {
    return (String) getProperty(ORDER_BY_KEY);
  }
 
 
   static {
    // register the new TYPE by family and rendererType
     TYPE.lockAndRegister(UIXObject.COMPONENT_FAMILY, RENDERER_TYPE);
   }
 
}

F.4.4 Example Renderer Class Code

The renderer class controls the display of a component. Example F-10 shows the renderer class for the custom TagPane component.

Example F-10 Renderer Class

package oracle.adfdemo.acme.faces.render;
 
import java.io.IOException;
 
import java.text.MessageFormat;
 
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.logging.Logger;
 
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
 
import oracle.adf.view.rich.render.ClientComponent;
import oracle.adf.view.rich.render.ClientEvent;
import oracle.adf.view.rich.render.ClientMetadata;
import oracle.adf.view.rich.render.RichRenderer;
 
import oracle.adfdemo.acme.faces.component.TagPane;
import oracle.adfdemo.acme.faces.event.TagSelectEvent;
 
import org.apache.myfaces.trinidad.bean.FacesBean;
import org.apache.myfaces.trinidad.bean.PropertyKey;
import org.apache.myfaces.trinidad.context.RenderingContext;
 
 
/**
 * <p>Renderer for {@link oracle.adfdemo.acme.faces.component.TagPane}
 * component.</p>
 */
public class TagPaneRenderer
  extends RichRenderer
{
 
  /**
   * <p>Java Logger instance.</p>
   */
  private static final Logger _LOG =
    Logger.getLogger(TagPaneRenderer.class.getName());
 
 
  /**
   * <p>No-args constructor passes the <code>TagPane.TYPE</code> to the
   * base class.  The type bean is used to extend the component properties
   * meta-data by invoking <code>findTypeConstants</code>.</p>
   */
  public TagPaneRenderer()
  {
    super(TagPane.TYPE);
  }
 
 
  /**
   * <p>Invoked by the base class, this is the hook to perform the markup
   * rendering for the {@link oracle.adfdemo.acme.faces.component.TagPane}.
   * </p>
   *
   * @param context faces context
   * @param arc rendering context
   * @param component {@link oracle.adfdemo.acme.faces.component.TagPane}
   * @param client server-side state for the client component
   * @param bean state holder for the TagPane component
   * @throws IOException error rendering markup
   */
  protected void encodeAll(FacesContext context, RenderingContext arc,
                           UIComponent component, ClientComponent client,
                           FacesBean bean)
    throws IOException
  {
 
    //defines this attribute to be pushed to the client component
    //this attribute is not secured so its value will prorogate
    //to the server when modified from the client
    client.addProperty(_ORDER_BY_KEY, bean.getProperty(_ORDER_BY_KEY));
 
    ResponseWriter writer = context.getResponseWriter();
 
    writer.startElement("div", component);
 
    // write the client id for the component
    renderId(context, component);
 
    // add the component root style attribute; factors in the inline and class 
    // style component properties
    renderRootStyleAttributes(context, arc, client, bean,
                              getDefaultStyleClass(context, arc, bean));
 
    writer.startElement("span", component);
 
    // writes the style class attribute using a skinning key;  the key
    // will need to be normalized and compressed
    renderStyleClass(context, arc, TagPaneRenderer._TAG_CONTENT_STYLE_KEY);
 
    _renderTags(context, component, arc, bean);
 
    writer.endElement("span");
 
    writer.endElement("div");
 
  }
 
  /**
   * <p>Renders the <code>tags</code> as anchored links ordered by
   * tag or tag weight.  The tag weight is converted into a font that is
   * evenly distributed between the <code>MAXIMUM_FONT_SIZE</code> and the
   * <code>MINIMUM_FONT_SIZE</code> based on the tag's weight.</p>
   *
   * @param context faces context
   * @param component {@link oracle.adfdemo.acme.faces.component.TagPane}
   * @param arc rendering context
   * @param bean state holder for {@link oracle.adfdemo.acme.faces.component.TagPane}
   * @throws IOException error during rendering tags
   */
  private void _renderTags(FacesContext context, UIComponent component,
                           RenderingContext arc, FacesBean bean)
    throws IOException
  {
    Map<String, Number> tags = _getTags(bean);
    if (tags.isEmpty())
    {
      return; // no work to do
    }
 
    // Calculates a font size for each tag.  The font size will be based on the
    // weight of the tag and the size proportional to the range of font sizes.
    Map<String, Integer> fontSizes =
      _computeFontSize(tags, _getMaximumFontSize(arc),
                       _getMinimumFontSize(arc));
 
    // create a list from the map's entry set.
    List<Map.Entry<String, Number>> entries =
      new ArrayList<Map.Entry<String, Number>>(tags.entrySet());
 
    //collocation sequence determined by the orderBy property
    Collections.sort(entries, _getComparator(bean));
 
    ResponseWriter writer = context.getResponseWriter();
 
    //for each tag, write an anchored tag.  The font size is explicitly set
    //using a inline style.
    for (Map.Entry<String, Number> entry: entries)
    {
      // start a hyperlink for each tag
      writer.startElement("a", component);
 
      // render the class style for the link
      renderStyleClass(context, arc, TagPaneRenderer._TAG_STYLE_KEY);
 
      writer.writeAttribute("href", "#", null);
 
      //font size is calculated from the _computeFontSize call above
      //the _getFontSizeStyle substitutes the font size parameter into the style
      String style = _getFontSizeStyle(fontSizes.get(entry.getKey()));
 
      //set the font size using an inline style
      writer.writeAttribute("style", style, null);
 
      //insert the tag weight into the title string
      String title = _getTitleStyle(entry.getValue().doubleValue(), arc);
 
      // write the title string attribute to the hyperlink
      writer.writeAttribute("title", title, null);
 
      //write body of the tag; the description of the link will
      //be the name of the tag
      writer.writeText(entry.getKey(), null);
 
      //end the hyperlink
      writer.endElement("a");
 
      // write a small spacer between anchored tags
      renderSpacer(context, arc, "2px", "2px");
    }
 
  }
 
  /**
   * <p>Substitutes the tag's <code>weight</code> into the pattern defined by
   * the <code>AcmeTagPane_tag_title</code> resource key.</p>
   * @param weight tag weight
   * @param arc rendering context
   * @return formatted title attribute for the anchored tag
   */
  private String _getTitleStyle(double weight, RenderingContext arc)
  {
    // title attribute template from the resource bundle
    MessageFormat titleFormat =
      new MessageFormat(arc.getTranslatedString("AcmeTagPane_tag_title"));
 
    return titleFormat.format(new Object[]
        { weight });
  }
 
  /**
   * <p>Substitutes the <code>size</code> into the style pattern defined by
   * the <code>_FONT_INLINESTYLE_FORMAT</code>.</p>
   * @param size font size
   * @return inline style defining the font size
   */
  private String _getFontSizeStyle(int size)
  {
    return _FONT_INLINESTYLE_FORMAT.format(new Object[]
        { size });
  }
 
  /**
   * <p>Returns the default constructor for our client-side component,
   * <code>oracle.adfdemo.acme.js.component.AcmeTagPane.js</code></p>
   *
   * @return client-side component name
   */
  protected String getClientConstructor()
  {
    return _CLIENT_COMPONENT;
  }
 
 
  /**
   * <p>Retrieves a hint on if and when a component must be sent down to the
   * client.</p>
   *
   * @return the client component type
   */
  @Override
  protected ClientComponent.Type getDefaultClientComponentType()
  {
    return ClientComponent.Type.CREATE_WITH_REQUIRED_ATTRS;
  }
 
  /**
   * <p>Retrieves the style class to apply to the root element, 
   * <code>_ROOT_STYLE_KEY</code>.</p>
   *
   * @param context the FacesContext
   * @param arc the RenderingContext
   * @param bean the FacesBean of the component to render
   * @return the root element's style class
   */
  @Override
  protected String getDefaultStyleClass(FacesContext context,
                                        RenderingContext arc,
                                        FacesBean bean)
  {
    return TagPaneRenderer._ROOT_STYLE_KEY;
  }
 
 
  /**
   * <p>Returns the weighted tag map from the component's state holder
   * properties bag using the <code>_TAGS_KEY</code>.</p>
   *
   * @param bean state holder for {@link
   * oracle.adfdemo.acme.faces.component.TagPane}
   * @return map of weighted tags
   */
  private Map<String, Number> _getTags(FacesBean bean)
  {
    Map<String, Number> tags =
      (Map<String, Number>) bean.getProperty(_TAGS_KEY);
    if (tags == null)
    {
      tags = Collections.emptyMap();
    }
 
    return tags;
  }
 
  /**
   * <p>Looks at the {@link oracle.adfdemo.acme.faces.component.TagPane}'s
   * <code>orderBy</code> property and returns a corresponding
   * <code>Comparator</code>.  The default is to sort descending by weight.
   * If <code>orderBy</code> equals "alpha", the order is sorted ascending
   * by the tag.</p>
   *
   * @param bean state holder for the {@link 
   *oracle.adfdemo.acme.faces.component.TagPane}
   * @return comparator to sort the <code>tags</code>
   */
  private Comparator<Map.Entry<String, Number>> _getComparator(FacesBean bean)
  {
    String orderBy = (String) bean.getProperty(_ORDER_BY_KEY);
    if (orderBy != null && orderBy.equalsIgnoreCase("alpha"))
    {
      return _sortAscByTag;
    }
 
    return this._sortDescByWeight;
  }
 
  /**
   * <p>This method is called from the <code>RichRenderer</code>'s implementation
   * of the <code>decode</code> method.  Within this method we will check to see
   * if there are any custom client events, 
   * <code>oracle.adfdemo.acme.js.event.AcmeTagSelectEvent</code>.
   * If a client event is present, we will queue a corresponding server-side faces 
   * event, {@link oracle.adfdemo.acme.faces.event.TagSelectEvent}.  This event is  
   * targeted for the apply request values phase so the response will be completed
   *  if a client event is found.
   * </p>
   *
   * @param facesContext faces context
   * @param component {@link oracle.adfdemo.acme.faces.component.TagPane} 
   * component
   * @param clientId unique component identifier
   */
  @Override
  public void decodeInternal(FacesContext facesContext,
                             UIComponent component, String clientId)
  {
 
    super.decodeInternal(facesContext, component, clientId);
 
    // look for a client event of type "tagSelect"
    ClientEvent clientEvent =
      this.getClientEvent(facesContext, clientId, _CLIENT_SELECT_EVENT_TYPE);
    if (clientEvent != null)
    {
      // extract the tag from the client event
      String tag =
        (String) clientEvent.getParameters().get(TagPaneRenderer._CLIENT_SELECT_EVENT_TAG_PARAM);
 
      _LOG.finest("Found SelectEvent with tag of " +
                  (tag != null? tag: "null"));
 
      // Instantiate a corresponding server side event
      TagSelectEvent event = new TagSelectEvent(component, tag);
 
      // push the event up to the view root
      event.queue();
 
      // this event is an assumed immediate meaning that we will stop the 
      //lifecycle after
      // the apply request values phase and short-circuit to render response.
      // there doesn't seem to be a good reason for this component to participate
      // in the process validations phase.  that is why we are going to jump to
      // the render response phase.
      facesContext.renderResponse();
    }
 
  }
 
  /**
   * <p>This method is called from the base constructor.  The callback gives 
   * opportunity to add client characteristics to the server-side component 
   * properties that become  client-side component properties.</p>
   *
   * @param type <code>FacesBean.TYPE</code>
   * @param metadata client specific extension to the <code>FacesBean.Type</code>
   */
  @Override
  protected void findTypeConstants(FacesBean.Type type,
                                   ClientMetadata metadata)
  {
    super.findTypeConstants(type, metadata);
 
    _TAGS_KEY = type.findKey("tags");
    metadata.addSecureProperty(_TAGS_KEY);
 
    _ORDER_BY_KEY = type.findKey("orderBy");
 
  }
 
  /**
   * <p>Calculates a proportional font weight for each of the <code>tags</code>
   * based on the weight of the tag entry.  The weight of each entry is
   * determined by the value of the <code>Map.Entry</code>.  The computed font
   * weight for each item will be between the <code>maxFontSize</code> and
   * <code>minFontSize</code>. Tags that have the same weight will be
   * displayed using the same font.</p>
   *
   * @param tags weighted tags
   * @param maxFontSize maximum font weight
   * @param minFontSize minimum font weight
   * @return Lookup map that contains the tag name as the key and the value
   * is the computed font size.
   */
  private Map<String, Integer> _computeFontSize(Map<String, Number> tags,
                                                double maxFontSize,
                                                double minFontSize)
  {
 
    double maxWeight = 0; // max weight
    double minWeight = 0; // min weight
 
    // find the min and max in the tag weight set
    for (Map.Entry<String, Number> entry: tags.entrySet())
    {
      // first time set the min to the first entry
      if (minWeight == 0)
      {
        minWeight = entry.getValue().doubleValue();
      }
 
      maxWeight = Math.max(maxWeight, entry.getValue().doubleValue());
      minWeight = Math.min(minWeight, entry.getValue().doubleValue());
    }
 
    //target map where the key is the tag and the value the font size
    Map<String, Integer> fontSizeMap = new TreeMap<String, Integer>();
 
 
    // for each entry, calculate a font size adding to the target
    // map by tag name
    for (Map.Entry<String, Number> entry: tags.entrySet())
    {
 
      double weight = entry.getValue().doubleValue();
      double percentTotaWeight =
        (weight - (minWeight - 1d)) / ((maxWeight + 1d));
      double fontSize =
        (percentTotaWeight * ((maxFontSize + 1d) - minFontSize)) +
        (minFontSize - 1d);
 
      //add to the xref map
      fontSizeMap.put(entry.getKey(), (int) Math.round(fontSize));
 
    }
 
    return fontSizeMap;
  }
 
  /**
   * <p>Returns the minimum font size that will be used as the lower limit when
   * assigning each unique tag weight a font size.  The value will be pulled from 
   * the skinning key "acme|tagPane-tr-minimum-font-size".  If the
   * key is not found or the value is not an integer, the
   * <code>_DEFAULT_MINIMUM_FONT_SIZE</code> will be used.</p>
   *
   * @param arc Rendering context
   * @return max font size assigned to a tag
   */
  private int _getMinimumFontSize(RenderingContext arc)
  {
    int size = _DEFAULT_MINIMUM_FONT_SIZE;
    String fontSize = (String)
      arc.getSkin().getProperty(_MINIMUM_FONT_SIZE_PROPERTY);
    if (fontSize != null)
    {
      try
      {
        size = Integer.parseInt(fontSize);
      }
      catch (NumberFormatException e)
      {
        _LOG.warning("The \"" + _MINIMUM_FONT_SIZE_PROPERTY +
                     "\" skin property " +
                     "is not defined or is not a valid integer. " +
                     "Using default minimum font size: " + size);
      }
    }
    return size;
  }
 
  /**
   * <p>Returns the maximum font size that will be used as the upper limit when
   * assigning each unique tag weight a font size.  The value will be pulled from 
   * the skinning key "acme|tagPane-tr-maximum-font-size".  If the
   * key is not found or the value is not an integer, the
   * <code>_DEFAULT_MAXIMUM_FONT_SIZE</code> will be used.</p>
   *
   * @param arc Rendering context
   * @return max font size assigned to a tag
   */
  private int _getMaximumFontSize(RenderingContext arc)
  {
    int size = _DEFAULT_MAXIMUM_FONT_SIZE;
    String fontSize = (String)
      arc.getSkin().getProperty(_MAXIMUM_FONT_SIZE_PROPERTY);
    if (fontSize != null)
    {
      try
      {
        size = Integer.parseInt(fontSize);
      }
      catch (NumberFormatException e)
      {
        _LOG.warning("The \"" + _MAXIMUM_FONT_SIZE_PROPERTY +
                   "\" skin property " +
                   "is not defined or is not a valid integer. " +
                   "Using default maximum font size: " + size);
      }
    }
    return size;
  }
 
 
  /**
   * <p>Sorts the <code>tags.entrySet</code> by map value in descending order
   * and by map key in ascending.
   * </p>
   */
  private Comparator<Map.Entry<String, Number>> _sortDescByWeight =
    new Comparator<Map.Entry<String, Number>>()
  {
    public int compare(Map.Entry<String, Number> o1,
                       Map.Entry<String, Number> o2)
    {
      double value1 = o1.getValue().doubleValue();
      double value2 = o2.getValue().doubleValue();
      if (value1 > value2)
      {
        return -1;
      }
      else if (value1 < value2)
      {
        return 1;
      }
      else
      {
        // sort by value DESC, key ASC
        return o1.getKey().compareTo(o2.getKey());
      }
    }
  };
 
 
  /**
   * <p>Sorts the <code>tags.entrySet</code> by the key in ascending order.
   * </p>
   */
  private Comparator<Map.Entry<String, Number>> _sortAscByTag =
    new Comparator<Map.Entry<String, Number>>()
  {
    public int compare(Map.Entry<String, Number> o1,
                       Map.Entry<String, Number> o2)
    {
      return o1.getKey().compareTo(o2.getKey());
    }
  };
 
 
  /**
   * <p>Default maximum font size for rendered tags (20).</p>
   */
  private static final int _DEFAULT_MAXIMUM_FONT_SIZE = 20;
 
 
  /**
   * <p>Minimum font size for rendered tags (2).</p>
   */
  private static final int _DEFAULT_MINIMUM_FONT_SIZE = 8;
 
  /**
   * <p>The client event type for  
   * <code>oracle.adfdemo.acme.js.event.AcmeTagSelectEvent.js</code>.
   * This constant will correspond to <code>AcmeTagSelectEvent.SELECT_EVENT_
   * TYPE</code>.</p>
   */
  private static final String _CLIENT_SELECT_EVENT_TYPE = "tagSelect";
 
  /**
   * <p>The tag parameter name on the 
   * <code>oracle.asfdemo.acme.js.event.AcmeTagSelectEvent.js</code>.
   * The tag reports one of the weighted tags the user has click on.  The
   * <code>AddMarshalledProperties</code> function is where this parameter is 
   * prepared to be sent to the server where it is intercepted by the
   * <code>oracle.adfinternal.view.faces.context.RichPhaseListener</code> and 
   * unmarshaled into a <code>oracle.adf.view.rich.render.ClientEvent</code>.
   * </p>
   *
   */
  private static final String _CLIENT_SELECT_EVENT_TAG_PARAM = "tag";
 
  /**
   * <p>The root skinning key <code>acme|tagPane</code>.</p>
   */
  private static final String _ROOT_STYLE_KEY = "acme|tagPane";
 
  /**
   * <p>The maximum font size skinning key 
   * <code>acme|tagPane-tr-maximum-font-size</code>.</p>
   */
  private static final String _MAXIMUM_FONT_SIZE_PROPERTY =
    _ROOT_STYLE_KEY + "-tr-maximum-font-size";
 
  /**
   * <p>The minimum font size skinning key 
   * <code>acme|tagPane-tr-minimum-font-size</code>.</p>
   */
  private static final String _MINIMUM_FONT_SIZE_PROPERTY =
    _ROOT_STYLE_KEY + "-tr-minimum-font-size";
 
  /**
   * <p>TagPane content skinning key <code>acme|tagPane::content</code>.</p>
   */
  private static final String _TAG_CONTENT_STYLE_KEY =
    "acme|tagPane::content";
 
  /**
   * <p>Tag link skinning key <code>acme|tagPane::tag</code>.</p>
   */
  private static final String _TAG_STYLE_KEY = "acme|tagPane::tag";
 
  /**
   * <p>The <code>tags</code> property key from the <code>TagPane.TYPE</code>.</p>
   */
  private static PropertyKey _TAGS_KEY = null;
 
  /**
   * <p>The <code>orderBy</code> property key from the 
   * <code>TagPane.TYPE</code>.</p>
   */
  private static PropertyKey _ORDER_BY_KEY = null;
 
  /**
   * <p>The Corresponding JavaScript component,
   * <code>oracle.adfdemo.acme.js.component.AcmeTagPane.js</code>.</p>
   */
  private static final String _CLIENT_COMPONENT = "AcmeTagPane";
 
  /**
   * <p>Pattern used to build the inline style that specifies the font
   * size for a tag.  Pixels units are assumed.</p>
   */
  private static final MessageFormat _FONT_INLINESTYLE_FORMAT =
    new MessageFormat("font-size:{0}px;");
 
}