/* * Copyright 2004-2010 Information & Software Engineering Group (188/1) * Institute of Software Technology and Interactive Systems * Vienna University of Technology, Austria * * 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.ifs.tuwien.ac.at/dm/somtoolbox/license.html * * 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 at.tuwien.ifs.somtoolbox.clustering; import org.apache.commons.lang.StringUtils; import prefuse.data.Node; import prefuse.data.Tree; public class HierarchicalCluster<E> extends Cluster<E> { public static final String COLUMN_NAME_LEVEL = "level"; public static final String COLUMN_NAME_CONTENT = "content"; public static final String COLUMN_NAME_CONTENT_LONG = "contentLong"; private double mergeCost; private HierarchicalCluster<E> leftNode; private HierarchicalCluster<E> rightNode; int size = -1; // cache of computation public HierarchicalCluster(E datum, String label) { super(datum, label); } public HierarchicalCluster(HierarchicalCluster<E> cluster1, HierarchicalCluster<E> cluster2) { super(); data.addAll(cluster1.getData()); data.addAll(cluster2.getData()); this.label = cluster1.getLabel() + " + " + cluster2.getLabel(); this.leftNode = cluster1; this.rightNode = cluster2; } public Node buildPrefuseTree(Tree tree, Node root) { Node n = tree.addChild(root); if (isLeaf()) { n.setString(COLUMN_NAME_LEVEL, toString()); n.setString(COLUMN_NAME_CONTENT, shortContentToString()); n.setString(COLUMN_NAME_CONTENT_LONG, contentToString()); } else { n.setString(COLUMN_NAME_LEVEL, leftNode.toString() + " + " + rightNode.toString()); n.setString(COLUMN_NAME_CONTENT, shortContentToString()); n.setString(COLUMN_NAME_CONTENT_LONG, contentToString()); leftNode.buildPrefuseTree(tree, n); rightNode.buildPrefuseTree(tree, n); } return n; } /** Cuts off the string when the content information is too long, but adds the number of surpressed cluster names. */ private String shortContentToString() { final String res = contentToString(); final int max = 75; if (res.length() < max) { return res; } else { String res2 = res.substring(0, max - 5); int endPoint = res2.lastIndexOf(CONTENT_SEPARATOR_CHAR); res2 = res2.substring(0, endPoint); final String res3 = res.substring(endPoint); final int more = StringUtils.countMatches(res3, CONTENT_SEPARATOR_CHAR); return res2 + " ... (" + more + " more)"; } } public HierarchicalCluster<E> getLeftNode() { return leftNode; } public double getMergeCost() { return mergeCost; } public double getMergeCostIncrease() { if (isLeaf()) { return getMergeCost(); } else { return getMergeCost() - (leftNode.getMergeCost() + rightNode.getMergeCost()); } } public HierarchicalCluster<E> getRightNode() { return rightNode; } public boolean isLeaf() { return leftNode == null && rightNode == null; } public void setMergeCost(double mergeCost) { this.mergeCost = mergeCost; } public int depth() { if (isLeaf()) { // leaf return 1; } else { // return left.size() + right.size(); if (size == -1) { size = leftNode.size() + leftNode.size(); } return size; } } @Override public String toString() { return "Cluster level #" + depth(); } public boolean contains(E element) { return getLeftNode() == element || getRightNode() == element || getLeftNode().contains(element) || getRightNode().contains(element); } }