You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by mc...@apache.org on 2008/05/12 23:21:23 UTC

svn commit: r655646 - /myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/ChildPropertyMenuModel.java

Author: mcooper
Date: Mon May 12 14:21:23 2008
New Revision: 655646

URL: http://svn.apache.org/viewvc?rev=655646&view=rev
Log:
Added a ChildPropertyMenuModel; similar to ChildPropertyTreeModel but in order to extend MenuModel, it must also implement getFocusRowKey().

Added:
    myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/ChildPropertyMenuModel.java   (with props)

Added: myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/ChildPropertyMenuModel.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/ChildPropertyMenuModel.java?rev=655646&view=auto
==============================================================================
--- myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/ChildPropertyMenuModel.java (added)
+++ myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/ChildPropertyMenuModel.java Mon May 12 14:21:23 2008
@@ -0,0 +1,414 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ * 
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.myfaces.trinidad.model;
+
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.faces.model.DataModel;
+
+import org.apache.myfaces.trinidad.logging.TrinidadLogger;
+
+/**
+ * Creates a MenuModel from a List of beans.
+ * To use this class you must have a tree of beans (or Maps).
+ * The structure of your tree must be a List (or array) of root beans, and each bean must have a
+ * getter method (or Map property) that returns the children List. All elements of your tree must be
+ * the same type.
+ * <P>
+ * Suppose you have a bean called EmpBean that contains the data for a particular employee. Suppose
+ * this bean has a method called getDirectReports() that returns a List of EmpBeans which are the
+ * direct reports of the employee. Suppose there is a List called "founders" which is the root list
+ * of EmpBeans. Now you can construct a MenuModel by calling:
+ * <pre>
+ * MenuModel model = new ChildPropertyMenuModel(founders, "directReports");
+ * </pre>
+ * Bean rules will be used to find an appropriate getter method for the "directReports" property.
+ * java.util.Maps are also supported instead of beans.
+ * <p>
+ * Example: Given the following class:
+ * <pre>
+ * public class Person
+ * {
+ *    public Person(String name)
+ *    {
+ *      _name = name;
+ *    }
+ *
+ *    public String getName()
+ *    {
+ *      return _name;
+ *    }
+ *
+ *    public List getKids()
+ *    {
+ *      return _kids;
+ *    }
+ *
+ *    private final String _name;
+ *    private final List _kids = new ArrayList();
+ * }
+ * </pre>
+ * You can construct a tree by:
+ * <pre>
+ * Person john = new Person("John Smith");
+ * Person kim = new Person("Kim Smith");
+ * Person tom = new Person("Tom Smith");
+ * Person ira = new Person("Ira Wickrememsinghe");
+ * Person mallika = new Person("Mallika Wickremesinghe");
+ *
+ * john.getKids().add(kim);
+ * john.getKids().add(tom);
+ * ira.getKids().add(mallika);
+ *
+ * // create the list of root nodes:
+ * List people = new ArrayList();
+ * people.add(john);
+ * people.add(ira);
+ * </pre>
+ * Now you can construct a MenuModel by:
+ * <pre>
+ * MenuModel model = new ChildPropertyMenuModel(people, "kids", focusRowKey);
+ * </pre>
+ */
+public class ChildPropertyMenuModel extends MenuModel
+{
+  /**
+   * Creates a MenuModel
+   * @param instance The Collection of root nodes of this tree.
+   *                 This can be a List or array of beans (or Maps).
+   *                 This instance is first converted into a CollectionModel (see
+   *                 {@link ModelUtils#toCollectionModel}).
+   * @param childProperty This property will be used to get at the child Lists from each bean (or
+   *                      Map). Bean rules will be used to find a getter method that matches this
+   *                      property. If each node is a Map, this property will be passed in to the
+   *                      Map's get method to get the child List.
+   * @param focusRowKey null or the row key in focus
+   */
+  public ChildPropertyMenuModel(Object instance, String childProperty, Object focusRowKey)
+  {
+    this();
+    setChildProperty(childProperty);
+    setWrappedData(instance);
+    this._focusRowKey = focusRowKey;
+  }
+
+  /**
+   * No-arg constructor for use with managed-beans.
+   * Must call the {@link #setChildProperty} and
+   * {@link #setWrappedData} methods after constructing this instance.
+   */
+  public ChildPropertyMenuModel()
+  {
+    Node root = new Node(null);
+    _path.add(root);
+  }
+
+  /**
+   * Gets the rowKey of the current row.
+   */
+  @Override
+  public Object getRowKey()
+  {
+    final int sz = _path.size() - 1;
+    Object lastRowkey = _getRowKey();
+    if ((sz == 0) && (lastRowkey == null))
+      return null;  // root collection
+    
+    // have to clone the path here. otherwise, we have to say that
+    // this tree model cannot be mutated while accessing the path
+    // returned by this method.
+    List<Object> path = new ArrayList<Object>(sz+1);
+    if (sz > 0)
+    {
+      for(int i=0; i<sz; i++)
+      {
+        Node node = _getNode(i);
+        path.add(node.childModel.getRowKey());
+      }
+    }
+    path.add(lastRowkey);
+    return path;
+  }
+
+  /**
+   * Selects a new current row. The row that matches the given rowKey is made current.
+   * @param rowKey use null to access the root collection 
+   */
+  @SuppressWarnings("unchecked")
+  @Override
+  public void setRowKey(Object rowKey)
+  {
+    Node root = _getNode(0);
+    _path.clear();
+    _path.add(root);
+    
+    List<Object> path = (List<Object>) rowKey;
+    if ((path == null) || (path.size() == 0))
+    {
+      setRowIndex(-1);
+      return;
+    }
+      
+    int lastIndex = path.size() - 1;
+    for(int i=0; i<lastIndex; i++)
+    {
+      Object pathKey = path.get(i);
+      _setRowKey(pathKey);
+      enterContainer();
+    }
+    
+    _setRowKey(path.get(lastIndex));
+  }
+
+  @SuppressWarnings("unchecked")
+  @Override
+  public Object getContainerRowKey(Object childKey)
+  {
+    List<Object> path = (List<Object>) childKey;
+    if ((path == null) || (path.size() <= 1))
+      return null;
+    // Make a copy of the sublist - subList does not return
+    // a serializable object
+    return new ArrayList<Object>(path.subList(0, path.size() - 1));
+  }
+
+  @Override
+  public int getRowCount()
+  {
+    return _getModel().getRowCount();
+  }
+
+  @Override
+  public Object getRowData()
+  {
+    return _getModel().getRowData();
+  }
+
+  @Override
+  public boolean isRowAvailable()
+  {
+    return _getModel().isRowAvailable();
+  }
+
+  @Override
+  public boolean isContainer()
+  {
+    Object rowData = getRowData();
+    Object value = getChildData(rowData);
+    
+    if (value != null)
+    {
+      if (value instanceof Collection<?>)
+      {
+        return !((Collection<?>)value).isEmpty();
+      }
+      else if (value.getClass().isArray())
+      {
+        return Array.getLength(value) > 0;
+      }
+      else if (value instanceof DataModel)
+      {
+        return ((DataModel)value).getRowCount() > 0;
+      }
+    }
+    
+    return value != null;
+  }
+
+  @Override
+  public void enterContainer()
+  {
+    Object rowData = getRowData();
+    if (rowData == null)
+      throw new IllegalStateException(_LOG.getMessage("NULL_ROWDATA"));
+    Node node = new Node(rowData);
+    _path.add(node);
+  }
+
+  @Override
+  public void exitContainer()
+  {
+    int sz = _path.size();
+    if (sz > 1)
+      _path.remove(sz - 1);
+    else
+      throw new IllegalStateException(_LOG.getMessage("CANNOT_EXIT_ROOT_CONTAINER"));
+  }
+  
+  /**
+   * Gets the instance being wrapped by this MenuModel.
+   */
+  @Override
+  public Object getWrappedData()
+  {
+    return _wrappedData;
+  }
+
+  /**
+   * Sets the instance being wrapped by this MenuModel.
+   * Calling this method sets the path to empty.
+   */
+  @Override
+  public void setWrappedData(Object data)
+  {
+    Node root = _getNode(0);
+    root.childModel = ModelUtils.toCollectionModel(data);
+    setRowKey(null);
+    _wrappedData = data;
+  }
+
+  /**
+   * Gets the property name used to fetch the children.
+   */
+  public final String getChildProperty()
+  {
+    return _childProperty;
+  }
+
+  /**
+   * Sets the property name used to fetch the children.
+   */
+  public final void setChildProperty(String childProperty)
+  {
+    _childProperty = childProperty;
+  }
+
+  @Override
+  public int getRowIndex()
+  {
+    return _getModel().getRowIndex();
+  }
+
+  @Override
+  public void setRowIndex(int rowIndex)
+  {
+    _getModel().setRowIndex(rowIndex);
+  }
+
+  @Override
+  public boolean isSortable(String property)
+  {
+    return _getModel().isSortable(property);
+  }
+
+  @Override
+  public List<SortCriterion> getSortCriteria()
+  {
+    return _getModel().getSortCriteria();
+  }
+
+  @Override
+  public void setSortCriteria(List<SortCriterion> criteria)
+  {
+    _getModel().setSortCriteria(criteria);
+  }
+
+  /**
+   * Gets the child data for a node. This child data will be converted into a CollectionModel by
+   * calling {@link #createChildModel}.
+   * @param parentData the node to get the child data from
+   * @return the List or array that is the child data.
+   * must return null for a leaf node.
+   */
+  protected Object getChildData(Object parentData)
+  {
+    String prop = getChildProperty();
+    if (prop == null)
+      return null;
+    
+    return SortableModel.__resolveProperty(parentData, prop);
+  }
+
+  /**
+   * Converts childData into a CollectionModel.
+   * This method calls {@link ModelUtils#toCollectionModel}
+   * @param childData the data to convert. This can be a List or array.
+   */
+  protected CollectionModel createChildModel(Object childData)
+  {
+    CollectionModel model = ModelUtils.toCollectionModel(childData);
+    model.setRowIndex(-1);
+    return model;
+  }
+
+  private Object _getRowKey()
+  {
+    return _getModel().getRowKey();
+  }
+
+  private void _setRowKey(Object key)
+  {
+    _getModel().setRowKey(key);
+  }
+  
+  private Node _getCurrentNode()
+  {
+    return _getNode(_path.size() - 1);
+  }
+
+  private Node _getNode(int index)
+  {
+    return _path.get(index);    
+  }
+
+  private CollectionModel _getModel()
+  {
+    Node node = _getCurrentNode();
+    CollectionModel model = node.childModel;
+  
+    if (model == null)
+    {
+      Object value = getChildData(node.parentData);
+      model = createChildModel(value);
+      node.childModel = model;
+    }
+    return model;
+  }
+
+  public Object getFocusRowKey()
+  {
+    return _focusRowKey;
+  }
+
+  public void setFocusRowKey(Object focusRowKey)
+  {
+    _focusRowKey = focusRowKey;
+  }
+
+  private static final class Node
+  {
+    public Node(Object parentData)
+    {
+      this.parentData = parentData;
+    }
+
+    public final Object parentData;
+    CollectionModel childModel = null;
+  }
+
+  private final List<Node> _path = new ArrayList<Node>(5);
+  private String _childProperty;
+  private Object _wrappedData;
+  private Object _focusRowKey;
+  private static final TrinidadLogger _LOG =
+    TrinidadLogger.createTrinidadLogger(ChildPropertyMenuModel.class);
+}
\ No newline at end of file

Propchange: myfaces/trinidad/trunk_1.2.x/trinidad-api/src/main/java/org/apache/myfaces/trinidad/model/ChildPropertyMenuModel.java
------------------------------------------------------------------------------
    svn:eol-style = native