/*
* NOTE: This copyright does *not* cover user programs that use HQ
* program services by normal system calls through the application
* program interfaces provided as part of the Hyperic Plug-in Development
* Kit or the Hyperic Client Development Kit - this is merely considered
* normal use of the program, and does *not* fall under the heading of
* "derived work".
*
* Copyright (C) [2004, 2005, 2006], Hyperic, Inc.
* This file is part of HQ.
*
* HQ is free software; you can redistribute it and/or modify
* it under the terms version 2 of the GNU General Public License as
* published by the Free Software Foundation. This program is distributed
* in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*/
package org.hyperic.hq.bizapp.shared.uibeans;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.hyperic.hq.appdef.shared.AppdefEntityID;
import org.hyperic.util.data.IResourceTreeNode;
import org.hyperic.util.data.ITreeNode;
/**
* Implementation of the resource tree node interface for rendering
* the navigation map.
*
*/
public class ResourceTreeNode extends TreeNode implements IResourceTreeNode {
private int type;
private AppdefEntityID rEntityId;
private AppdefEntityID[] pEntityIds;
private int ctype = NO_CTYPE;
private boolean promotable;
/**
* Creates a promotable <code>ResourceTreeNode</code> instance for a
* resource. The resource may be promoted to an auto-group with one
* parent resource at a later time.
*
* @param name the name
* @param desc the description
* @param rEntityId the resource's entity id
* @param pEntityId the Appdef parent entity id
* @param ctype the ctype
* @param type the type of this node
*/
public ResourceTreeNode(String name, String desc, AppdefEntityID rEntityId,
AppdefEntityID pEntityId, int ctype ) {
super(name, desc);
this.pEntityIds = new AppdefEntityID[] { pEntityId };
this.rEntityId = rEntityId;
this.ctype = ctype;
this.type = ResourceTreeNode.RESOURCE;
this.promotable = true;
}
/**
* Creates a promotable <code>ResourceTreeNode</code> instance for a
* resource. The resource may be promoted to an auto-group at a later
* time.
*
* @param name the name
* @param desc the description
* @param rEntityId the resource's entity id
* @param pEntityIds the Appdef parent entity ids
* @param ctype the ctype
*/
public ResourceTreeNode(String name, String desc, AppdefEntityID rEntityId,
AppdefEntityID[] pEntityIds, int ctype ) {
super(name, desc);
this.pEntityIds = pEntityIds;
this.rEntityId = rEntityId;
this.ctype = ctype;
this.type = ResourceTreeNode.RESOURCE;
this.promotable = true;
}
/**
* Creates a new <code>ResourceTreeNode</code> instance for an
* auto-group with one parent resource.
*
* @param name the name
* @param desc the description
* @param pEntityId the Appdef parent entity id
* @param ctype the ctype
* @param type the type of this node
*/
public ResourceTreeNode(String name, String desc, AppdefEntityID pEntityId,
int ctype, int type) {
super(name, desc);
this.pEntityIds = new AppdefEntityID[] { pEntityId };
this.rEntityId = null;
this.ctype = ctype;
assertValidType(type);
this.type = type;
this.promotable = false;
}
/**
* Creates a new <code>ResourceTreeNode</code> instance for an
* auto-group with multiple parent resources.
*
* @param name the name
* @param desc the description
* @param pEntityIds the Appdef parent entity ids
* @param ctype the ctype
* @param type the type of this node
*/
public ResourceTreeNode(String name, String desc, AppdefEntityID[] pEntityIds,
int ctype, int type) {
super(name, desc);
this.pEntityIds = pEntityIds;
this.rEntityId = null;
this.ctype = ctype;
assertValidType(type);
this.type = type;
this.promotable = false;
}
/**
* Creates a new <code>ResourceTreeNode</code> instance for a
* resource.
*
* @param name the name
* @param desc the description
* @param pEntityIds the Appdef parent entity ids
* @param ctype the ctype
* @param type the type of this node
*/
public ResourceTreeNode(String name, String desc, AppdefEntityID rEntityId,
int type ) {
super(name, desc);
this.rEntityId = rEntityId;
this.pEntityIds = null;
this.ctype = NO_CTYPE;
assertValidType(type);
this.type = type;
this.promotable = false;
}
public static void autoGroupData (ResourceTreeNode[] data) {
// only first node contains children
ResourceTreeNode parent = data[0];
// Process up and down children, promoting duplicate resources
// into autogroups as applicable
ITreeNode[] children = promoteResources(parent.getUpChildren());
Arrays.sort(children,new TreeNodeAlphaComparator(true));
for (int x=0;x<children.length;x++) {
children[x].reset();
}
parent.replaceUpChildren(children);
children = promoteResources(parent.getDownChildren());
Arrays.sort(children,new TreeNodeAlphaComparator());
for (int x=0;x<children.length;x++) {
children[x].reset();
}
parent.replaceDownChildren(children);
}
public static void alphaSortNodes (ResourceTreeNode[] children) {
alphaSortNodes(children,false);
}
public static void alphaSortNodes (ResourceTreeNode[] children,
boolean reverse) {
Arrays.sort(children,new TreeNodeAlphaComparator(reverse));
}
private static ITreeNode[] promoteResources (ITreeNode[] children) {
// Process downchildren
Map typeMap;
List childrenList;
List newChildrenList;
typeMap = new LinkedHashMap();
newChildrenList = new ArrayList();
if (children != null) {
childrenList = java.util.Arrays.asList(children);
for (Iterator i=childrenList.iterator();i.hasNext();) {
ResourceTreeNode rtn = (ResourceTreeNode)i.next();
if (rtn.isPromotable()) {
if (typeMap.containsKey(rtn.getDescription())) {
rtn.promote();
}
typeMap.put(rtn.getDescription(),rtn);
} else {
newChildrenList.add(rtn);
}
}
newChildrenList.addAll(typeMap.values());
children = (ITreeNode[]) newChildrenList.toArray(new ITreeNode[0]);
}
/* debug
System.out.println ("promoteResources RETURNS "+children.length+" CHILDREN");
for (int x=0;x<children.length;x++) {
System.out.println ("child:"+children[x].toString());
} */
return children;
}
/**
* If our type is a resource, then we return the resource ids.
* If our type is an AUTO_GROUP then we return the parent ids.
*/
public AppdefEntityID[] getEntityIds () {
if (type == AUTO_GROUP) {
return pEntityIds;
} else {
return new AppdefEntityID[] { rEntityId };
}
}
/**
* Return the type of this node.
*
* @return the node type
*/
public int getType() {
return type;
}
/**
* Set the type of this node.
*
* @param type the node type
*/
public void setType(int type) {
this.type = type;
}
/**
* Is this node promotable to an auto-group
*
* @return true if promotable, false if not
*/
public boolean isPromotable () {
return (type == RESOURCE && this.promotable);
}
/**
* Overridden from <code>TreeNode</code> to ensure that the array
* is of type IResourceTreeNode[].
*/
public ITreeNode[] getUpChildren() {
return (IResourceTreeNode[])
upChildren.toArray(new IResourceTreeNode[0]);
}
/**
* Overridden from <code>TreeNode</code> to ensure that the array
* is of type IResourceTreeNode[].
*/
public ITreeNode[] getDownChildren() {
return (IResourceTreeNode[])
downChildren.toArray(new IResourceTreeNode[0]);
}
/**
* Get the resource's Appdef entity id.
*
* @return rEntityId Appdef entity id
*/
public AppdefEntityID getREntityId() {
return rEntityId;
}
/**
* Get the parents' Appdef entity ids.
*
* @return pEntityIds the Appdef entity ids
*/
public AppdefEntityID[] getPEntityIds() {
return pEntityIds;
}
/**
* Set the resource's Appdef entity id.
*
* @param pEntityIds the Appdef entity id
*/
public void setREntityId(AppdefEntityID rEntityId) {
this.rEntityId = rEntityId;
}
/**
* Set the parents' Appdef entity ids.
*
* @param pEntityIds the Appdef entity ids
*/
public void setPEntityIds(AppdefEntityID[] pEntityIds) {
this.pEntityIds = pEntityIds;
}
/**
* Get the ctype.
*
* @return the ctype
*/
public int getCtype() {
return ctype;
}
/**
* Set the ctype.
*
* @param ctype the ctype
*/
public void setCtype(int ctype) {
this.ctype = ctype;
}
/**
* Determines whether two objects are equal.
*
* @return true or false
*/
public boolean equals (Object o) {
if (!(o instanceof ResourceTreeNode)) {
return false;
}
ResourceTreeNode other = (ResourceTreeNode)o;
if ( super.equals((Object)other) &&
other.getCtype() == this.getCtype() &&
other.getType() == this.getType() &&
other.getUpChildren().length == this.getUpChildren().length &&
other.getDownChildren().length == this.getDownChildren().length ){
return true;
}
return false;
}
/**
* Returns the hashcode of this object.
*
* @return hash code.
*/
public int hashCode(){
int result = 17 + super.hashCode();
int pri = 37;
result = pri * result + this.ctype;
result = pri * result + this.type;
result = pri * result + getUpChildren().length;
result = pri * result + getDownChildren().length;
if (getREntityId()!=null) {
result = pri * result + getREntityId().getID();
result = pri * result + getREntityId().getType();
}
if (getPEntityIds() != null) {
result = pri * result + getPEntityIds().length;
for (int x=0;(getPEntityIds()!=null && x<getPEntityIds().length);x++) {
result = pri * result + this.getPEntityIds()[x].hashCode();
}
}
return result;
}
/**
* Returns true if this node is an autogroup and has a ctype,
* false otherwise.
*
* @return true or false
*/
public boolean hasCtype() {
if (type == AUTO_GROUP) {
return (ctype != NO_CTYPE);
} else {
return false;
}
}
/**
* Promote a resource node to an auto-group node.
*/
public void promote () {
if (isPromotable()) {
setName(getDescription()); // an auto-group's name is same as desc
this.type = AUTO_GROUP; // change our type to AG
this.promotable = false;
}
}
/**
* Return a string representation of this node.
*
* @return string representation of this node
*/
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append("[")
.append(" name=").append( getName() )
.append(" desc=").append( getDescription() )
.append(" ctype=").append( getCtype() )
.append(" type=").append( getType() )
.append(" rid=").append( getREntityId() )
.append(" pids=").append( getPEntityIds() )
.append(" up-children: ").append( getUpChildren().length )
.append(" down-chilren: ").append( getDownChildren().length )
.append(" ]");
return buf.toString();
}
//------------------------------------------------------------------------------------
//-- private helpers
//------------------------------------------------------------------------------------
private void assertValidType(int type) {
if (! (type >= NONE && type <= CLUSTER) ) {
throw new IllegalArgumentException("Invalid Type: " + type);
}
}
}
// EOF