import clojure.lang.PersistentHashSet;
import clojure.lang.IPersistentSet;

import java.util.Set;
import java.util.List;
import java.util.Iterator;

class Classifier {
    static class Category {
        Category parent;
        String   name;
        Set      keywords;

        Category(Category parent, String name, 
                 Set keywords) {
            this.parent = parent;
            this.name = name;
            this.keywords = keywords;
        }

        Set keys() {
            return (Set)unionKeys((IPersistentSet)keywords);
        }

        private IPersistentSet unionKeys(IPersistentSet 
                                         other) {
            Iterator i = keywords.iterator();
            while (i.hasNext()) {
                other = (IPersistentSet)other.cons(i.next());
            }
            if (parent != null)
                return parent.unionKeys(other);
            return other;
        }
    };

    static Category makeChild(Category parent, String name,
                               String ... keywords) {
        PersistentHashSet newSet = PersistentHashSet.EMPTY;
        for (String k : keywords) {
            newSet = (PersistentHashSet)newSet.cons(k);
        }
        Category c = new Category(parent, name, newSet);
        return c;
    }

    static Category world = 
        new Category(null, "everything", 
                     PersistentHashSet.EMPTY);

    static Category physics = 
        makeChild(world, "physics", new String[]
            {"matter", "energy", "motion", "spacetime", 
             "force"});

    static Category classicalMechanics = 
        makeChild(physics, "classical-mechanics", 
                   new String[]
            {"newton", "force", "body", "mass", "action",
             "reaction", "velocity", "euclidean", "speed"});

    static Category quantumMechanics = 
        makeChild(physics, "quantum-mechanics", new String[]
            {"energy", "matter", "wave", "particle", 
             "duality", "planck", "entanglement", 
             "collapse"});

    static void print_keywords_of(Category cat) {
        System.out.println("Category " + cat.name + 
                           " contains the keywords:");
        System.out.println(cat.keys());
    }

    public static void main(String[] args) {
        print_keywords_of(physics);
        print_keywords_of(classicalMechanics);
    }
}
