/*
* Copyright 2004 original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.extremecomponents.tree;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.extremecomponents.table.core.TableModel;
/**
* org.extremecomponents.tree.model.BaseModelUtils.java -
*
* @author phorn
*/
public final class TreeModelUtils {
private static Log logger = LogFactory.getLog(TreeModelUtils.class);
private TreeModelUtils() {
}
/**
* Recursively loads the tree structure into the treeList attribute and sets
* the treeList as the collection to use.
* @param model TableModel
* @param rows java.util.Collection
* @return
* @throws Exception
*/
public static List<TreeNode> loadTreeStructure(TableModel model, Collection rows) throws Exception {
List<TreeNode> result = new ArrayList<TreeNode>();
List search = new ArrayList();
search.addAll(rows);
for (Iterator iter = search.iterator(); iter.hasNext();) {
Object bean = iter.next();
String parentAttribute = model.getTableHandler().getTable().getAttributeAsString(TreeConstants.PARENT_ATTRIBUTE);
Object parentId = BeanUtils.getProperty(bean, parentAttribute);
if (parentId == null || StringUtils.isBlank(parentId + "")) {
// Load up the top level parents
TreeNode node = new TreeNode(bean, getBeanId(model, bean), 0);
result.add(node);
iter.remove();
loadChildren(model, result, search, node, 0);
}
}
return result;
}
public static void loadChildren(TableModel model, List displayList, Collection searchList, TreeNode node, int currentDepth) throws Exception {
currentDepth++;
List subList = new ArrayList();
subList.addAll(searchList);
Object id = node.getIdentifier();
String key = getNodeKey(model, id);
Map openNodes = (Map) model.getTableHandler().getTable().getAttribute(TreeConstants.OPEN_NODES);
if (openNodes.get(key) != null) {
node.setOpen(true);
} else {
node.setOpen(false);
}
for (Iterator iter = subList.iterator(); iter.hasNext();) {
Object bean = iter.next();
if (nodeIsBeanParent(model, node, bean)) {
TreeNode childNode = new TreeNode(bean, getBeanId(model, bean), currentDepth);
node.addChild(childNode);
childNode.setParent(node);
iter.remove();
if (isOpen(model, node, true)) {
displayList.add(childNode);
}
loadChildren(model, displayList, subList, childNode, currentDepth); // Recurse
}
}
}
public static boolean nodeIsBeanParent(TableModel model, TreeNode node, Object bean) throws Exception {
String parentAttribute = model.getTableHandler().getTable().getAttributeAsString(TreeConstants.PARENT_ATTRIBUTE);
Object parent = PropertyUtils.getProperty(bean, parentAttribute);
if (parent != null)
logger.debug("parent instanceof " + parent.getClass().getName());
if (parent == null || StringUtils.isBlank(parent + "")) {
return false;
}
Object nodeId = node.getIdentifier();
Object parentId = getBeanId(model, parent);
if (node.getBean().equals(parent))
return true;
if (nodeId.equals(parentId))
return true;
return false;
}
public static Object getBeanId(TableModel model, Object bean) throws Exception {
try {
String identifier = model.getTableHandler().getTable().getAttributeAsString(TreeConstants.IDENTIFIER);
return PropertyUtils.getProperty(bean, identifier);
} catch (NoSuchMethodException e) {
return bean;
}
}
/**
* Find out if the node and all parents are open.
*/
public static boolean isOpen(TableModel model, TreeNode node, boolean filterControlled) {
boolean filtered = model.getLimit().isFiltered();
boolean cleared = model.getLimit().isCleared();
if (filterControlled && filtered && !cleared) {
node.setOpen(true);
return true;
}
if (!node.isOpen()) {
return false;
}
if (node.getParent() == null) {
return true;
}
return isOpen(model, node.getParent(), filterControlled);
}
/**
* @return Returns the parameter key used to indicate this node is open.
*/
public static String getNodeKey(TableModel model, Object id) {
return model.getTableHandler().prefixWithTableId() + TreeConstants.OPEN + id;
}
}