org.carrot2.core.ClusterWithParent Maven / Gradle / Ivy
Show all versions of carrot2-mini Show documentation
/*
* Carrot2 project.
*
* Copyright (C) 2002-2013, Dawid Weiss, Stanisław Osiński.
* All rights reserved.
*
* Refer to the full license file "carrot2.LICENSE"
* in the root folder of the repository checkout or at:
* http://www.carrot2.org/carrot2.LICENSE
*/
package org.carrot2.core;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import com.google.common.collect.Lists;
/**
* Wraps a {@link Cluster} to add information about the cluster's parent cluster, if any.
* A reference to the parent cluster is not kept directly in the {@link Cluster} class
* because some algorithms may attach a single cluster to many parent clusters.
*
* Instances of this class override {@link #hashCode()} and {@link #equals(Object)} by
* forwarding them to {@link #cluster}.
*/
public final class ClusterWithParent
{
/** The cluster wrapped by this class */
public final Cluster cluster;
/**
* The parent cluster of {@link #cluster}, may be null
in case of
* top-level clusters.
*/
public final ClusterWithParent parent;
/**
* Subclusters of {@link #cluster} wrapped to add their parent cluster. The list is
* unmodifiable.
*/
public final List subclusters;
/**
* Private constructor.
*/
private ClusterWithParent(ClusterWithParent parent, Cluster cluster,
List subclusters)
{
if (cluster == null)
{
throw new IllegalArgumentException();
}
this.parent = parent;
this.cluster = cluster;
this.subclusters = subclusters;
}
/**
* Wraps a cluster hierarchy starting with the root
into
* {@link ClusterWithParent} objects. All children of the root
cluster
* will have the {@link #parent} field set to the wrapper corresponding to their
* parent clusters, while for the root
cluster, {@link #parent} will be
* null
. Note that for efficiency reasons, reference cycles are
* not detected.
*
* @param root the cluster to be wrapped
* @return wrapped cluster with parent
*/
public static ClusterWithParent wrap(Cluster root)
{
return wrap(null, root);
}
/**
* Private method that does the actual wrapping.
*/
private static ClusterWithParent wrap(ClusterWithParent parent, Cluster root)
{
final List actualSubclusters = root.getSubclusters();
final List subclustersWithParent = Lists
.newArrayListWithExpectedSize(actualSubclusters.size());
final ClusterWithParent rootWithParent = new ClusterWithParent(parent, root,
Collections.unmodifiableList(subclustersWithParent));
for (Cluster actualCluster : actualSubclusters)
{
subclustersWithParent.add(wrap(rootWithParent, actualCluster));
}
return rootWithParent;
}
/**
* Wraps a list of top level clusters. Each cluster in the list will be assumed to
* have a null
parent cluster. Note that for efficiency reasons,
* reference cycles are not detected.
*
* @param clusters the list of top-level clusters to be wrapped
* @return the wrapped clusters with parents
*/
public static List wrap(List clusters)
{
final List result = Lists.newArrayListWithExpectedSize(clusters
.size());
for (Cluster cluster : clusters)
{
result.add(wrap(cluster));
}
return result;
}
/**
* Locate the first cluster that has id equal to id
. The search
* includes all the clusters in the input and their sub-clusters. The
* first cluster with matching identifier is returned or null
* if no such cluster could be found.
*/
public static ClusterWithParent find(int id, Collection wrappers)
{
for (ClusterWithParent c : wrappers)
{
if (c != null)
{
if (c.cluster.id != null && c.cluster.id == id)
{
return c;
}
if (!c.cluster.getSubclusters().isEmpty())
{
final ClusterWithParent sub = find(id, c.subclusters);
if (sub != null)
{
return sub;
}
}
}
}
return null;
}
/*
*
*/
@Override
public int hashCode()
{
return cluster == null ? 0 : cluster.hashCode();
}
/*
*
*/
@Override
public boolean equals(Object obj)
{
if (obj == this)
return true;
if (obj instanceof ClusterWithParent)
{
return this.cluster.equals(((ClusterWithParent) obj).cluster);
}
return false;
}
}