org.carrot2.core.ClusterWithParent.java Source code

Java tutorial

Introduction

Here is the source code for org.carrot2.core.ClusterWithParent.java

Source

/*
 * Carrot2 project.
 *
 * Copyright (C) 2002-2012, Dawid Weiss, Stanisaw Osiski.
 * 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.
 * <p>
 * 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 <code>null</code> 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<ClusterWithParent> subclusters;

    /**
     * Private constructor.
     */
    private ClusterWithParent(ClusterWithParent parent, Cluster cluster, List<ClusterWithParent> subclusters) {
        if (cluster == null) {
            throw new IllegalArgumentException();
        }

        this.parent = parent;
        this.cluster = cluster;
        this.subclusters = subclusters;
    }

    /**
     * Wraps a cluster hierarchy starting with the <code>root</code> into
     * {@link ClusterWithParent} objects. All children of the <code>root</code> cluster
     * will have the {@link #parent} field set to the wrapper corresponding to their
     * parent clusters, while for the <code>root</code> cluster, {@link #parent} will be
     * <code>null</code>. Note that for efficiency reasons, reference cycles are
     * <strong>not</strong> 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<Cluster> actualSubclusters = root.getSubclusters();
        final List<ClusterWithParent> 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 <code>null</code> parent cluster. Note that for efficiency reasons,
     * reference cycles are <strong>not</strong> detected.
     * 
     * @param clusters the list of top-level clusters to be wrapped
     * @return the wrapped clusters with parents
     */
    public static List<ClusterWithParent> wrap(List<Cluster> clusters) {
        final List<ClusterWithParent> result = Lists.newArrayListWithExpectedSize(clusters.size());

        for (Cluster cluster : clusters) {
            result.add(wrap(cluster));
        }

        return result;
    }

    /**
     * Locate the first cluster that has id equal to <code>id</code>. The search
     * includes all the clusters in the input and their sub-clusters. The
     * first cluster with matching identifier is returned or <code>null</code>
     * if no such cluster could be found.
     */
    public static ClusterWithParent find(int id, Collection<ClusterWithParent> 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;
    }
}