public static void gen(
            int stage,
            String unigramDir,  // Unigram directory.
            String trigramDir,  // Trigram directory.
            String outputDir,   // Output directory.
            String name)        // Output file.
            throws Exception
    {
        unigramDir = new File(unigramDir).getAbsolutePath();
        trigramDir = new File(trigramDir).getAbsolutePath();
        long initTime, startTime, endTime;
        try {
            System.out.println();
            System.out.println("------------------------------------------------------------------------------");
            System.out.println("STAGE " + stage + " CORPUS PREPROCESS");
            System.out.println();
            
            initTime = System.currentTimeMillis();
            
            String tempDir = new File(outputDir, "temp").getPath();
            if (!new File(outputDir).exists())
                FileUtils.forceMkdir(new File(outputDir));
            if (!(new File(tempDir)).exists())
                FileUtils.forceMkdir(new File(tempDir));
            
            /*STEP1 Unigram Pre-process */
            startTime = System.currentTimeMillis();
            System.out.print("STEP 1: Unigram Preprocess..");
            UnigramPreprocess.unigramGen(unigramDir, tempDir, ".*");
            endTime = System.currentTimeMillis();
            System.out.println("DONE!\n\tTime taken: " + ((endTime - startTime) / 1000.0) + " second.");
            /* STEP2 Trigram Count Summation */
            startTime = endTime;
            System.out.print("STEP 2: Trigram Count Summation..");
            TrigramCountSummation.TrigramGen(trigramDir, tempDir, ".*");
            endTime = System.currentTimeMillis();
            System.out.println("DONE!\n\tTime taken: " + ((endTime - startTime) / 1000.0) + " second.");
            /* STEP3 External sort */
            startTime = endTime;
            System.out.print("STEP 3 : External Sorting..");
            TrigramExternalSort.sortFile(tempDir);
            endTime = System.currentTimeMillis();
            System.out.println("DONE!\n\tTime Taken: " + ((endTime - startTime) / 1000.0) + " second.");
            startTime = endTime;
            if (stage == 1) {
                /* STEP4 Frequency Print */
                System.out.print("STEP 4: Frequency Print..");
                FrequencyPrint.processT(tempDir);
            } else if (stage == 2) {
                /* STEP4 Word Relatedness Calculation */
                System.out.print("STEP 4: Word Relateness Calculation..");
                WordrtComputation.processT(tempDir);
            } else {
                throw new RuntimeException("Invalid stage number: " + stage);
            }
            endTime = System.currentTimeMillis();
            System.out.println("DONE!\n\tTime taken: " + ((endTime - startTime) / 1000.0) + " second.");
            /* STEP5 Binary Conversion */
            startTime = System.currentTimeMillis();
            System.out.print("STEP 5: Binary Conversion...");
            UnigramBinaryConversion.process(tempDir);
            TrigramBinaryConvertion.process(tempDir);
            endTime = System.currentTimeMillis();
            System.out.println("DONE!\n\tTime taken: " + ((endTime - startTime) / 1000.0) + " second.");

            FileUtil.getFileInDirectoryWithSuffix(tempDir, UnigramBinaryConversion.SUFFIX).renameTo(
                    new File(outputDir, name + '.' + Unigram.BINARY_SUFFIX));
            FileUtil.getFileInDirectoryWithSuffix(tempDir, TrigramBinaryConvertion.SUFFIX).renameTo(
                    new File(outputDir, name + '.' + Trigram.BINARY_SUFFIX));

            endTime = System.currentTimeMillis();
            System.out.println("PREPROCESS Done! Total time taken: " + ((endTime - initTime) / 1000.0) + " second.");
            System.out.println("------------------------------------------------------------------------------");
            System.out.println();

        } catch (Exception e) {
            System.out.println();
            System.out.println("PREPROCESS fail");
            System.out.println("------------------------------------------------------------------------------");
            System.out.println();
            throw e;
        }
    }