void write(JDefinedClass c) {
        // first collect all the types and identifiers
        mode = Mode.COLLECTING;
        d(c);

        javaLang = c.owner()._package("java.lang");

        // collate type names and identifiers to determine which types can be imported
        for( ReferenceList tl : collectedReferences.values() ) {
            if(!tl.collisions(c) && !tl.isId()) {
                assert tl.getClasses().size() == 1;

                // add to list of collected types
                importedClasses.add(tl.getClasses().get(0));
            }
        }

        // the class itself that we will be generating is always accessible
        importedClasses.add(c);

        // then print the declaration
        mode = Mode.PRINTING;

        assert c.parentContainer().isPackage() : "this method is only for a pacakge-level class";
        JPackage pkg = (JPackage) c.parentContainer();
        if (!pkg.isUnnamed()) {
            nl().d(pkg);
            nl();
        }

        // generate import statements
        JClass[] imports = importedClasses.toArray(new JClass[importedClasses.size()]);
        Arrays.sort(imports);
        for (JClass clazz : imports) {
            // suppress import statements for primitive types, built-in types,
            // types in the root package, and types in
            // the same package as the current type
            if(!supressImport(clazz, c)) {
                if (clazz instanceof JNarrowedClass) {
                    clazz = clazz.erasure();
                }
                
                p("import").p(clazz.fullName()).p(';').nl();
            }
        }
        nl();

        d(c);
    }