All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opentripplanner.graph_builder.AnnotationsToHTML Maven / Gradle / Ivy

package org.opentripplanner.graph_builder;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.*;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.*;
import java.util.logging.Level;

import org.apache.commons.io.FileUtils;
import org.opentripplanner.graph_builder.annotation.GraphBuilderAnnotation;
import org.opentripplanner.graph_builder.services.GraphBuilderModule;
import org.opentripplanner.routing.graph.Graph;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This class generates nice HTML graph annotations reports 
 * 
 * They are created with the help of getHTMLMessage function in {@link GraphBuilderAnnotation} derived classes.
 * @author mabu
 */
public class AnnotationsToHTML implements GraphBuilderModule {

    private static Logger LOG = LoggerFactory.getLogger(AnnotationsToHTML.class); 

    //Path to output folder
    private File outPath;

    //If there are more then this number annotations are split into multiple files
    //This is because browsers aren't made for giant HTML files which can be made with 500k annotations
    private int maxNumberOfAnnotationsPerFile;


    //This counts all occurrences of HTML annotations classes
    //If one annotation class is split into two files it has two entries in this Multiset
    //IT is used to show numbers in HTML files name and links
    Multiset annotationClassOccurences;

    //List of writers which are used for actual writing annotations to HTML
    List writers;

    //Key is classname, value is annotation message
    //Multimap because there are multiple annotations for each classname
    private Multimap annotations;
  
    public AnnotationsToHTML (File outpath, int maxNumberOfAnnotationsPerFile) {
        this.outPath = outpath;
        annotations = ArrayListMultimap.create();
        this.maxNumberOfAnnotationsPerFile = maxNumberOfAnnotationsPerFile;
        this.writers = new ArrayList<>();
        this.annotationClassOccurences = HashMultiset.create();
    }


    @Override
    public void buildGraph(Graph graph, HashMap, Object> extra) {

        if (outPath == null) {
            LOG.error("Saving folder is empty!");
            return;
        }

        outPath = new File(outPath, "report");
        if (outPath.exists()) {
            //Removes all files from report directory
            try {
                FileUtils.cleanDirectory(outPath);
            } catch (IOException e) {
                LOG.error("Failed to clean HTML report directory: " + outPath.toString() + ". HTML report won't be generated!", e);
                return;
            }
        } else {
            //Creates report directory if it doesn't exist yet
            try {
                FileUtils.forceMkdir(outPath);
            } catch (IOException e) {
                e.printStackTrace();
                LOG.error("Failed to create HTML report directory: " + outPath.toString() + ". HTML report won't be generated!", e);
                return;
            }
        }



        //Groups annotations in multimap according to annotation class
        for (GraphBuilderAnnotation annotation : graph.getBuilderAnnotations()) {
            //writer.println("

" + annotation.getHTMLMessage() + "

"); // writer.println("" + annotation.getClass().getSimpleName()+""); addAnnotation(annotation); } LOG.info("Creating Annotations log"); //Creates list of HTML writers. Each writer has whole class of HTML annotations //Or multiple HTML writers can have parts of one class of HTML annotations if number // of annotations is larger than maxNumberOfAnnotationsPerFile for (Map.Entry> entry: annotations.asMap().entrySet()) { List annotationsList; if (entry.getValue() instanceof List) { annotationsList = (List) entry.getValue(); } else { annotationsList = new ArrayList<>(entry.getValue()); } addAnnotations(entry.getKey(), annotationsList); } //Actual writing to the file is made here since // this is the first place where actual number of files is known (because it depends on annotations count) for (HTMLWriter writer : writers) { writer.writeFile(annotationClassOccurences, false); } try { HTMLWriter indexFileWriter = new HTMLWriter("index", (Multimap)null); indexFileWriter.writeFile(annotationClassOccurences, true); } catch (FileNotFoundException e) { LOG.error("Index file coudn't be created:{}", e); } LOG.info("Annotated logs are in {}", outPath); } /** * Creates file with given class of annotations * * If number of annotations is larger then maxNumberOfAnnotationsPerFile multiple files are generated. * And named annotationClassName1,2,3 etc. * * @param annotationClassName name of annotation class and then also filename * @param annotations list of all annotations with that class */ private void addAnnotations(String annotationClassName, List annotations) { try { HTMLWriter file_writer; if (annotations.size() > 1.2*maxNumberOfAnnotationsPerFile) { LOG.debug("Number of annotations is very large. Splitting: {}", annotationClassName); List> partitions = Lists.partition(annotations, maxNumberOfAnnotationsPerFile); for (List partition: partitions) { annotationClassOccurences.add(annotationClassName); int labelCount = annotationClassOccurences.count(annotationClassName); file_writer =new HTMLWriter(annotationClassName+Integer.toString(labelCount), partition); writers.add(file_writer); } } else { annotationClassOccurences.add(annotationClassName); int labelCount = annotationClassOccurences.count(annotationClassName); file_writer = new HTMLWriter(annotationClassName + Integer.toString(labelCount), annotations); writers.add(file_writer); } } catch (FileNotFoundException ex) { LOG.error("Output folder not found:{} {}", outPath, ex); } } @Override public void checkInputs() { } /** * Groups annotations according to annotation class name * * All annotations are saved together in multimap where key is annotation classname * and values are list of annotations with that class * @param annotation */ private void addAnnotation(GraphBuilderAnnotation annotation) { String className = annotation.getClass().getSimpleName(); annotations.put(className, annotation.getHTMLMessage()); } class HTMLWriter { private PrintStream out; private Multimap writerAnnotations; private String annotationClassName; public HTMLWriter(String key, Collection annotations) throws FileNotFoundException { LOG.debug("Making file: {}", key); File newFile = new File(outPath, key +".html"); FileOutputStream fileOutputStream = new FileOutputStream(newFile); this.out = new PrintStream(fileOutputStream); writerAnnotations = ArrayListMultimap.create(); writerAnnotations.putAll(key, annotations); annotationClassName = key; } public HTMLWriter(String filename, Multimap curMap) throws FileNotFoundException { LOG.debug("Making file: {}", filename); File newFile = new File(outPath, filename +".html"); FileOutputStream fileOutputStream = new FileOutputStream(newFile); this.out = new PrintStream(fileOutputStream); writerAnnotations = curMap; annotationClassName = filename; } private void writeFile(Multiset classes, boolean isIndexFile) { println("Graph report for " + outPath.getParentFile() + "Graph.obj"); println("\t"); println(""); println(""); println( ""); String css = "\t\t\n" + ""; println(css); println(""); println(String.format("

OpenTripPlanner annotations log for %s

", annotationClassName)); println("

Graph report for " + outPath.getParentFile() + "Graph.obj

"); println("

"); //adds links to the other HTML files for (Multiset.Entry htmlAnnotationClass : classes.entrySet()) { String label_name = htmlAnnotationClass.getElement(); String label; int currentCount = 1; //it needs to add link to every file even if they are split while (currentCount <= htmlAnnotationClass.getCount()) { label = label_name + currentCount; if (label.equals(annotationClassName)) { println(String.format("", label_name.toLowerCase(), label)); } else { println(String.format("%s", label_name.toLowerCase(), label, label)); } currentCount++; } } println("

"); if (!isIndexFile) { println("
    "); writeAnnotations(); println("
"); } println(""); close(); } /** * Writes annotations as LI html elements */ private void writeAnnotations() { String annotationFMT = "
  • %s
  • "; for (Map.Entry annotation: writerAnnotations.entries()) { print(String.format(annotationFMT, annotation.getValue())); } } private void println(String bodyhtml) { out.println(bodyhtml); } private void print(String bodyhtml) { out.print(bodyhtml); } private void close() { out.close(); } /** * Generates JSON from annotations variable which is used by Javascript * to display HTML report */ private void writeJson() { try { out.print("\tvar data="); ObjectMapper mapper = new ObjectMapper(); JsonGenerator jsonGenerator = mapper.getJsonFactory().createJsonGenerator(out); mapper.writeValue(jsonGenerator, writerAnnotations.asMap()); out.println(";"); } catch (IOException ex) { java.util.logging.Logger.getLogger(AnnotationsToHTML.class.getName()).log(Level.SEVERE, null, ex); } } } }




    © 2015 - 2024 Weber Informatics LLC | Privacy Policy