public static void main()

in icon-scripts/hidpi-icons/src/main/java/org/netbeans/build/icons/IconTasks.java [69:314]


    public static void main(String[] args) throws IOException {
        final File ICON_SCRIPTS_DIR = new File(System.getProperty("user.dir"), "../");
        if (!new File(ICON_SCRIPTS_DIR, "hidpi-icons/src/main/java/org/netbeans/build/icons/IconTasks.java").exists()) {
            System.err.println("Error: Working directory must be icon-scripts/hidpi-icons");
            System.exit(-1);
        }

        if (args.length != 1) {
            System.err.println("Usage: IconTasks <netbeans repo directory>");
            System.err.println();
            System.err.println("(Working directory must be icon-scripts/hidpi-icons )");
            System.exit(-1);
        }

        final File NBSRC_DIR = new File(args[0]);
        if (!new File(NBSRC_DIR, "platform/core.windows/build.xml").exists()) {
            System.err.println("Path " + args[0] + " (in command-line argument) is not a cloned NetBeans repository");
            System.exit(-1);
        }
        final File ILLUSTRATOR_SVGS_DIR =
                new File(ICON_SCRIPTS_DIR, "illustrator_exports/");
        final File TABLES_DIR = new File(ICON_SCRIPTS_DIR, "tables/");
        final File ICON_HASHES_FILE = new File(TABLES_DIR, "icon-hashes.txt");
        final File MAPPINGS_FILE = new File(TABLES_DIR, "mappings.tsv");
        final File READY_ARTBOARDS_FILE = new File(TABLES_DIR, "ready-artboards.txt");
        final File ICONS_HTML_FILE = new File(NBSRC_DIR, "icons.html");
        boolean copySVGfiles =
                ILLUSTRATOR_SVGS_DIR.listFiles(f-> f.toString().endsWith(".svg")).length > 0;
        System.out.println("Using icon hashes file     : " + ICON_HASHES_FILE);
        System.out.println("Using mappings file        : " + MAPPINGS_FILE);
        System.out.println("Using ready-artboards file : " + READY_ARTBOARDS_FILE);
        if (copySVGfiles) {
            System.out.println("Copying SVG files from     : " + ILLUSTRATOR_SVGS_DIR);
        } else {
            System.out.println("The " + ILLUSTRATOR_SVGS_DIR +
                " folder has no SVGs in it to copy. " +
                "Will verify the existence of existing SVG files in the NetBeans repo only.");
        }

        ImmutableMap<IconPath, Hash> iconHashesByFile =
                readIconHashesByFile(NBSRC_DIR, ICON_HASHES_FILE);
        ImmutableSetMultimap<Hash, IconPath> filesByHash = Util.reverse(iconHashesByFile);
        ImmutableMap<Hash, Dimension> dimensionsByHash = readImageDimensions(NBSRC_DIR, filesByHash);
        // iconHashesByFile.forEach((key, value) -> System.out.println(key + " : " + value));

        ImmutableMap<IconPath, ArtboardName> artboardByFile =
                readArtboardByFileMappings(NBSRC_DIR, MAPPINGS_FILE);
        // artboardByFile.forEach((key, value) -> System.out.println(key + " : " + value));

        ImmutableSet<ArtboardName> readyArtboards = readReadyArtboards(READY_ARTBOARDS_FILE);

        SetMultimap<ArtboardName,Hash> hashesByArtboard = LinkedHashMultimap.create();
        for (Entry<IconPath, ArtboardName> entry : artboardByFile.entrySet()) {
            IconPath ip = entry.getKey();
            ArtboardName artboard = entry.getValue();
            Hash hash = Util.getChecked(iconHashesByFile, ip);
            hashesByArtboard.put(artboard, hash);
        }

        Set<ArtboardName> unknownReadyArtboards =
                Sets.difference(readyArtboards, hashesByArtboard.keySet());
        if (!unknownReadyArtboards.isEmpty()) {
            throw new RuntimeException("Unknown artboards " + unknownReadyArtboards);
        }
        if (copySVGfiles) {
            for (ArtboardName artboard : readyArtboards) {
                File artboardSVGFile = getIllustratorSVGFile(ILLUSTRATOR_SVGS_DIR, artboard);
                if (!artboardSVGFile.exists()) {
                    System.out.println("Illustrator export " + artboardSVGFile + " not found; skipping.");
                }
            }
        }

        // hashesByArtboard.asMap().forEach((key, value) -> System.out.println(key + " : " + value));

        Map<IconPath, ArtboardName> newArtboardByFile = Maps.newLinkedHashMap();

        for (Entry<ArtboardName, Hash> entry : hashesByArtboard.entries()) {
            ArtboardName artboard = entry.getKey();
            Hash hash = entry.getValue();
            List<IconPath> pathsForThisHash = Lists.newArrayList(filesByHash.get(hash));
            pathsForThisHash.sort((e1, e2) -> e1.toString().compareTo(e2.toString()));
            for (IconPath ip : pathsForThisHash) {
                Util.putChecked(newArtboardByFile, ip, artboard);
            }
        }

        ArtboardName UNASSIGNED_ARTBOARD = new ArtboardName("(no assigned artboard)");
        {
            List<Entry<IconPath,Dimension>> unassignedIcons = Lists.newArrayList();
            for (Entry<IconPath, Hash> entry : iconHashesByFile.entrySet()) {
                IconPath ip = entry.getKey();
                Hash hash = entry.getValue();
                Dimension dim = Util.getChecked(dimensionsByHash, hash);
                if (dim.width <= 64 && dim.height <= 64 && dim.width > 1 && dim.height > 1) {
                    unassignedIcons.add(new SimpleEntry(ip, dim));
                }
            }
            /* Order unassigned icons by width, then by height, then by path. (If there are multiple
            paths, the first path will end up being used for sorting per putIfAbsent below.) */
            unassignedIcons.sort((e1, e2) -> {
                int ret = Integer.compare(e1.getValue().width, e2.getValue().width);
                if (ret == 0) {
                    ret = Integer.compare(e1.getValue().height, e2.getValue().height);
                }
                if (ret == 0) {
                    ret = e1.getKey().toString().compareTo(e2.getKey().toString());
                }
                return ret;
            });
            for (Entry<IconPath,Dimension> entry : unassignedIcons) {
                newArtboardByFile.putIfAbsent(entry.getKey(), UNASSIGNED_ARTBOARD);
            }
        }

        // newArtboardByFile.forEach((key, value) -> System.out.println(key + " : " + value));
        ImmutableSetMultimap<ArtboardName, IconPath> filesByArtboard =
                Util.reverse(newArtboardByFile);

        for (ArtboardName artboard : readyArtboards) {
            final String svgContentToWrite;
            if (copySVGfiles) {
                svgContentToWrite = prepareSVGWithInsertedLicense(ILLUSTRATOR_SVGS_DIR, artboard);
            } else {
                svgContentToWrite = null;
            }
            for (IconPath ip : filesByArtboard.get(artboard)) {
                if (shouldIgnoreFile(ip)) {
                    continue;
                }
                IconPath destSVG = getSVGIconPath(ip);
                // System.out.println(srcSVGFile + "\t" + destSVG);
                File destSVGFile = new File(NBSRC_DIR, destSVG.toString());
                if (svgContentToWrite != null) {
                    try (PrintWriter pw = createPrintWriter(destSVGFile)) {
                        pw.print(svgContentToWrite);
                    }
                    System.out.println("Copied SVG file to " + destSVGFile);
                } else {
                    if (!destSVGFile.exists()) {
                        throw new RuntimeException(destSVGFile + " does not exist, and no " +
                                "SVGs to copy exist in the illustrator_exports directory.");
                    }
                    System.out.println("Verified existence of SVG file " + destSVGFile);
                }
            }
        }

        /* The mappings file is assumed to be in a git repo so that the user of the script can
        see what changed from run to run. */
        try (PrintWriter mappingsPW = createPrintWriter(MAPPINGS_FILE);
             PrintWriter htmlPW = createPrintWriter(ICONS_HTML_FILE))
        {
            htmlPW.println(LICENSE_HEADER);
            htmlPW.println("""
                <html>
                <head>
                <title>NetBeans Icons</title>
                <!--The the image paths in this file assume that this HTML file is located in the
                    root of a clone of the NetBeans source repository. To use images from a specific
                    GitHub branch (e.g. belonging to a pull request), a line like the following can
                    be included here:
                  <base href="https://raw.githubusercontent.com/eirikbakke/incubator-netbeans/pr-svgs240612/">
                -->
                <style>
                table td, table td * { vertical-align: top; margin-left: 5px; }
                thead td { padding-right: 10px; padding-bottom: 10px; }
                td { padding-right: 10px; }
                thead { font-weight: bold; }
                </style></head><body>
                <h1>NetBeans Bitmap and SVG Icons</h1>
                <p>This file lists bitmap icon files (GIF and PNG) in the NetBeans repo along with
                   their mapping to corresponding modernized SVG versions where available. A single
                   "artboard name" is assigned to icons that are exact or near duplicates, or which
                   are intended to have the same meaning.
                <p>This file is generated by the
                <tt>icon-scripts/hidpi-icons</tt> script in the
                <a href="https://github.com/apache/netbeans-tools">netbeans-tools</a>
                repository. Image paths are relative to the root of the NetBeans
                <a href="https://github.com/apache/netbeans">source repository</a>.
                <p>See the <a href="https://github.com/apache/netbeans-tools/tree/master/icon-scripts#readme">README</a>,
                    <a href="https://cwiki.apache.org/confluence/display/NETBEANS/SVG+Icon+Style+Guide+and+Process">Style Guide</a>, and
                    <a href="https://vimeo.com/667860571">Icon Drawing Video Tutorial</a> for more information.
                """
            );
            htmlPW.println("""
                <p><table border='0' cellpadding='1' cellspacing='0'>
                <thead><tr><td>Artboard Name<td>SVG<td>Bitmap<td>Dim<td>Path of Bitmap in
                  Source Repo (no icon image means same as for previous row)</tr></thead>""");
            int artboardIdx = 0;
            Set<ArtboardName> artboardsInOrder = Sets.newLinkedHashSet();
            artboardsInOrder.addAll(Sets.filter(filesByArtboard.keySet(), a -> readyArtboards.contains(a)));
            artboardsInOrder.addAll(filesByArtboard.keySet());
            for (ArtboardName artboard : artboardsInOrder) {
                List<IconPath> ips = Lists.newArrayList(filesByArtboard.get(artboard));
                ips.removeIf(ip -> shouldIgnoreFile(ip));
                /* Make sure to retain the original order, except keep files with the same hash
                together. */
                Map<Hash,Integer> order = Maps.newLinkedHashMap();
                for (IconPath ip : ips) {
                    order.putIfAbsent(Util.getChecked(iconHashesByFile, ip), order.size());
                }
                ips.sort((ip1, ip2) -> Integer.compare(
                        Util.getChecked(order, Util.getChecked(iconHashesByFile, ip1)),
                        Util.getChecked(order, Util.getChecked(iconHashesByFile, ip2))));
                int subRowIdx = 0;
                Hash previousHash = null;
                for (IconPath ip : ips) {
                    Hash hash = Util.getChecked(iconHashesByFile, ip);
                    if (!UNASSIGNED_ARTBOARD.equals(artboard)) {
                        mappingsPW.println(artboard + "  " + ip);
                    }

                    htmlPW.print(artboardIdx % 2 == 0 ? "<tr>" :
                            "<tr style='background: #eee'>");
                    if (subRowIdx == 0) {
                        htmlPW.print("<td rowspan='" + ips.size() + "'>" + artboard);
                        htmlPW.print("<td rowspan='" + ips.size() + "'>");
                        if (readyArtboards.contains(artboard)) {
                            htmlPW.print("<img src='" + getSVGIconPath(ip) + "'>");
                        }
                    }
                    htmlPW.print("<td>");
                    if (!hash.equals(previousHash)) {
                        htmlPW.print("<img src='" + ip + "'>");
                    }
                    htmlPW.print("<td>");
                    if (!hash.equals(previousHash)) {
                        Dimension dim = Util.getChecked(dimensionsByHash, hash);
                        htmlPW.print(dim.width + "x" + dim.height);
                    }
                    htmlPW.print("<td>" + ip);
                    htmlPW.println("</tr>");
                    previousHash = hash;
                    subRowIdx++;
                }
                artboardIdx++;
            }
            htmlPW.println("</table>");
            htmlPW.println("</body>");
        }

        System.out.println(
                "A summary of bitmap icons, SVG icons, and artboard name mappings was generated here:");
        System.out.println(ICONS_HTML_FILE);
    }