BufferedWriter out = new BufferedWriter(new FileWriter(output));
FileOutputStream fos = new FileOutputStream(output); OutputStreamWriter osr = new OutputStreamWriter(fos, "UTF-8"); PrintWriter out = new PrintWriter(osr);
    public static void processReport(Context context, String myFormat,                                      String myInput, String myOutput,                                     String myMap)        throws Exception, SQLException    {        startTime = new GregorianCalendar();                // set the parameters for this analysis        setParameters(myFormat, myInput, myOutput, myMap);                // pre prepare our standard file readers and buffered readers        FileReader fr = null;        BufferedReader br = null;                // read the input file        readInput(input);                // load the log file action to human readable action map        readMap(map);                // create the relevant report type        // FIXME: at the moment we only support HTML report generation        Report report = null;        if (format.equals("html"))        {            report = new HTMLReport();        }                report.setStartDate(startDate);        report.setEndDate(endDate);        report.setMainTitle(name, serverName);                // define our standard variables for re-use        // FIXME: we probably don't need these once we've finished re-factoring        Iterator keys = null;        int i = 0;        String explanation = null;        int value;                // FIXME: All of these sections should probably be buried in their own        // custom methods                Statistics overview = new Statistics();                overview.setSectionHeader("General Overview");                Iterator summaryEntries = generalSummary.iterator();        while (summaryEntries.hasNext())        {            String entry = (String) summaryEntries.next();            if (actionAggregator.containsKey(entry))            {                int count = Integer.parseInt((String) actionAggregator.get(entry));                overview.add(new Stat(translate(entry), count));            }        }                report.addBlock(overview);                // prepare the archive statistics package        if (archiveStats.size() > 0)        {            Statistics archiveInfo = prepareStats(archiveStats, true, false);            archiveInfo.setSectionHeader("Archive Information");            archiveInfo.setStatName("Content Type");            archiveInfo.setResultName("Number of items");                    report.addBlock(archiveInfo);        }                                // process the items in preparation to be displayed.  This includes sorting        // by view number, building the links, and getting further info where        // necessary        Statistics viewedItems = new Statistics("Item/Handle", "Number of views", itemFloor);        viewedItems.setSectionHeader("Items Viewed");                Stat[] items = new Stat[itemAggregator.size()];                keys = itemAggregator.keySet().iterator();        i = 0;        while (keys.hasNext())        {            String key = (String) keys.next();            String link = url + "handle/" + key;            value = Integer.parseInt((String) itemAggregator.get(key));            items[i] = new Stat(key, value, link);            i++;        }                Arrays.sort(items);                String info = null;        for (i = 0; i < items.length; i++)        {            if (i < itemLookup)            {                info = getItemInfo(context, items[i].getKey());            }                           // if we get something back from the db then set it as the key,            // else just use the link            if (info != null)            {                items[i].setKey(info  + " (" + items[i].getKey() + ")");            }            else            {                items[i].setKey(items[i].getReference());            }                        // reset the info register            info = null;        }                viewedItems.add(items);                report.addBlock(viewedItems);                // prepare a report of the full action statistics        Statistics fullInfo = prepareStats(actionAggregator, true, true);        fullInfo.setSectionHeader("All Actions Performed");        fullInfo.setStatName("Action");        fullInfo.setResultName("Number of times");                report.addBlock(fullInfo);                // prepare the user login statistics package        if (!userEmail.equals("off"))        {            Statistics userLogins = prepareStats(userAggregator, true, false);            userLogins.setSectionHeader("User Logins");            userLogins.setStatName("User");            userLogins.setResultName("Number of logins");            if (userEmail.equals("alias"))            {                explanation = "(distinct addresses)";                userLogins.setExplanation(explanation);            }                    report.addBlock(userLogins);        }        // prepare the search word statistics package        Statistics searchWords = prepareStats(searchAggregator, true, false);        searchWords.setSectionHeader("Words Searched");        searchWords.setStatName("Word");        searchWords.setResultName("Number of searches");        searchWords.setFloor(searchFloor);                report.addBlock(searchWords);                // FIXME: because this isn't an aggregator it can't be passed to        // prepareStats; should we overload this method for use with this kind        // of data?        // prepare the average item views statistics        if (avgItemViews > 0)        {            Statistics avg = new Statistics();            avg.setSectionHeader("Averaging Information");            Stat[] average = new Stat[1];                    average[0] = new Stat("Average views per item", avgItemViews);            avg.add(average);            report.addBlock(avg);        }                      // prepare the log line level statistics        // FIXME: at the moment we only know about warnings, but future versions        // should aggregate all log line levels and display here        Statistics levels = new Statistics("Level", "Number of lines");        levels.setSectionHeader("Log Level Information");                Stat[] level = new Stat[1];        level[0] = new Stat("Warnings", warnings);                levels.add(level);                report.addBlock(levels);                // get the display processing time information        Calendar endTime = new GregorianCalendar();        long timeInMillis = (endTime.getTimeInMillis() - startTime.getTimeInMillis());        int outputProcessTime = (new Long(timeInMillis).intValue() / 1000);                // prepare the processing information statistics        Statistics process = new Statistics("Operation", "");        process.setSectionHeader("Processing Information");                Stat[] proc = new Stat[3];        proc[0] = new Stat("Log Processing Time", processTime);        proc[0].setUnits("seconds");        proc[1] = new Stat("Output Processing Time", outputProcessTime);        proc[1].setUnits("seconds");        proc[2] = new Stat("Log File Lines Analysed", logLines);        proc[2].setUnits("lines");                process.add(proc);                report.addBlock(process);                // finally write the string into the output file        try         {            BufferedWriter out = new BufferedWriter(new FileWriter(output));            out.write(report.render());            out.close();        }         catch (IOException e)         {            System.out.println("Unable to write to output file " + output);            System.exit(0);        }                return;    }