org.wikipedia.nirvana.nirvanabot.BotReporter.java Source code

Java tutorial

Introduction

Here is the source code for org.wikipedia.nirvana.nirvanabot.BotReporter.java

Source

/**
 *  @(#)BotReporter.java 
 *  Copyright  2014 Dmitry Trofimovich (KIN, Nirvanchik, DimaTrofimovich@gmail.com)
 *  
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * WARNING: This file may contain Russian characters.
 * Recommended code page for this file is CP1251 (also called Windows-1251).
 * */

package org.wikipedia.nirvana.nirvanabot;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import javax.security.auth.login.LoginException;

import org.wikipedia.nirvana.FileTools;
import org.wikipedia.nirvana.NirvanaWiki;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * @author kin
 *
 */
public class BotReporter {
    public static final String DEFAULT_CACHE_FOLDER = "cache";
    public static final String DEFAULT_CACHE_FILE = "report_cache.js";
    private static org.apache.log4j.Logger log;
    NirvanaWiki wiki;
    ArrayList<ReportItem> reportItems;
    Calendar timeStarted;
    Calendar timeFinished;

    private int portalsTotal;
    private int portalsChecked;
    private int portalsProcessed;
    private int portalsUpdated;
    private int portalsError;

    String version;

    private String preambula = "";

    static {
        log = org.apache.log4j.Logger.getLogger(BotReporter.class.getName());
    }

    public BotReporter(NirvanaWiki wiki, int capacity, boolean started, String version, String preambulaFile) {
        this.wiki = wiki;
        this.version = version;
        reportItems = new ArrayList<ReportItem>(capacity);
        if (started) {
            botStarted(true);
        }
        if (preambulaFile != null && !preambulaFile.isEmpty()) {
            preambula = FileTools.readFileSilently(preambulaFile, "");
            if (!preambula.isEmpty() && !preambula.endsWith("\n")) {
                preambula += "\n";
            }
        }
    }

    public void botStarted(boolean log) {
        timeStarted = Calendar.getInstance();
        if (log) {
            logStartStatus();
        }
    }

    public void botFinished(boolean log) {
        timeFinished = Calendar.getInstance();
        if (log) {
            logEndStatus();
        }
    }

    public void setTotal(int total) {
        portalsTotal = total;
    }

    public void addToTotal(int num) {
        portalsTotal += num;
    }

    public void portalChecked() {
        portalsChecked++;
    }

    public void portalProcessed() {
        portalsProcessed++;
    }

    public void portalUpdated() {
        portalsUpdated++;
    }

    public void portalError() {
        portalsError++;
    }

    /**
      * @param reportItem
      */
    public void add(ReportItem reportItem) {
        reportItems.add(reportItem);
    }

    public void report() {

    }

    public void updateStartStatus(String page, String template) throws LoginException, IOException {
        String text = String.format("{{%1$s|status=1|starttime=%2$tF %2$tT|version=%3$s}}", template, timeStarted,
                version);
        wiki.edit(page, text, " ");
    }

    public void updateEndStatus(String page, String template) throws LoginException, IOException {
        String text = String.format(
                "{{%1$s|status=0|starttime=%2$tF %2$tT|endtime=%3$tF %3$tT|time=%4$s"
                        + "|total=%5$d|checked=%6$d|processed=%7$d|updated=%8$d|errors=%9$d|version=%10$s}}",
                template, timeStarted, timeFinished, printTimeDiff(timeStarted, timeFinished), portalsTotal,
                portalsChecked, portalsProcessed, portalsUpdated, portalsError, version);
        wiki.edit(page, text, " ");
    }

    public void updateStatus() {

    }

    public void reportTXT(String fileName) {
        if (timeFinished == null) {
            timeFinished = Calendar.getInstance();
        }
        if (!fileName.endsWith(".txt")) {
            fileName = fileName + ".txt";
        }
        log.info("generating report (TXT) . . .");
        StringBuilder sb = new StringBuilder();
        //StringBuffer sbuf = new StringBuffer();
        sb.append(ReportItem.getHeaderTXT()).append("\r\n");
        for (ReportItem item : reportItems) {
            sb.append(item.toStringTXT());
            sb.append("\r\n");
        }
        sb.append(ReportItem.getFooterTXT());
        try {
            FileTools.writeFile(sb.toString(), fileName);
        } catch (IOException e) {
            log.error(e.toString());
            e.printStackTrace();
        }
        log.info("report is generated!");
    }

    public void reportWiki(String reportPage, boolean mainLaunch) {
        // 1) Load old data (if any)
        String path = DEFAULT_CACHE_FOLDER + "\\" + DEFAULT_CACHE_FILE;
        File file = new File(path);
        List<ReportItem> oldData = null;
        if (file.exists()) {
            log.debug("File with old data found: " + path);
            // Check last modification time. Ignore if it's too old
            long lastModTime = file.lastModified();
            if (lastModTime != 0) {
                Calendar c = Calendar.getInstance();
                c.add(Calendar.DAY_OF_MONTH, -1);
                if (lastModTime > c.getTimeInMillis()) {
                    log.debug("Load old data");
                    oldData = load(file);
                }
            }
            log.debug("Delete old data");
            file.delete();
        }
        // 2) Merge with old data (if any)
        if (oldData != null) {
            merge(oldData);
        }
        // 3) Report to wiki or save to file
        if (mainLaunch) {
            doReportWiki(reportPage);
        } else {
            save(file);
        }
    }

    public void merge(List<ReportItem> data) {
        log.debug("Merge old data");
        // 3 cases here:
        // 1) lists are equal (ideal)
        // 2) left has values that right has not
        // 3) right has values that left has not
        ArrayList<ReportItem> right = new ArrayList<ReportItem>(data);
        for (ReportItem r : reportItems) {
            for (int j = 0; j < right.size(); j++) {
                if (r.equals(right.get(j))) {
                    ReportItem rMerge = right.get(j);
                    r.merge(rMerge);
                    right.remove(j);
                    break;
                }
            }
        }
        reportItems.addAll(right);
    }

    public void doReportWiki(String reportPage) {
        if (timeFinished == null) {
            timeFinished = Calendar.getInstance();
        }
        log.info("generating report (Wiki) . . .");
        StringBuilder sb = new StringBuilder();
        sb.append(preambula);
        sb.append(ReportItem.getHeaderWiki()).append("\n");
        int i = 0;
        for (ReportItem item : reportItems) {
            sb.append(item.toStringWiki(i));
            sb.append("\n");
            i++;
        }
        sb.append(ReportItem.getFooterWiki());

        try {
            wiki.edit(reportPage, sb.toString(), "     ");
        } catch (LoginException | IOException e) {
            log.error("Failed to update report.", e);
        }
    }

    /**
      * 
      */

    private void logStartStatus() {
        log.info(String.format("BOT STARTED %1$tF %1$tT version: %2$s", timeStarted, version));
    }

    public void logStatus() {
        log.info("portals: " + String.valueOf(portalsTotal) + ", checked: " + String.valueOf(portalsChecked)
                + ", processed: " + String.valueOf(portalsProcessed) + ", updated: "
                + String.valueOf(portalsUpdated) + ", errors: " + String.valueOf(portalsError));
    }

    private void logEndStatus() {
        long start = timeStarted.getTimeInMillis();
        long end = timeFinished.getTimeInMillis();
        log.info(String.format("BOT STARTED %1$tF %1$tT", timeStarted));
        log.info(String.format("BOT FINISHED %1$tF %1$tT ", timeFinished));
        log.info("FULL WORK TIME: " + printTimeDiff(end - start));
    }

    public static String printTimeDiff(Calendar time1, Calendar time2) {
        long start = time1.getTimeInMillis();
        long end = time2.getTimeInMillis();
        return printTimeDiff(end - start);
    }

    public static String printTimeDiff(long diff) {
        int hours = (int) ((diff) / (60L * 60L * 1000L));
        int min = (int) ((diff) / (60L * 1000L) - (long) hours * 60L);
        int sec = (int) ((diff) / (1000L) - (long) hours * 60L * 60L - (long) min * 60L);
        return String.format("%d h %d m %d s", hours, min, sec);
    }

    public List<ReportItem> load(File file) {
        ObjectMapper mapper = new ObjectMapper();
        List<ReportItem> items = null;
        try {
            items = mapper.readValue(file, new TypeReference<List<ReportItem>>() {
            });
        } catch (IOException e1) {
            log.error(e1);
            return null;
        }
        return items;
    }

    public void save(File file) {
        ObjectMapper mapper = new ObjectMapper();
        try {
            mapper.writeValue(file, reportItems);
        } catch (JsonParseException e) {
            log.error(e);
            return;
        } catch (JsonMappingException e) {
            log.error(e);
            return;
        } catch (IOException e) {
            log.error(e);
            return;
        }
        log.info("report items successfully saved to " + file.getPath());
    }
}