ReportBuilder.scala 5.13 KB
Newer Older
1
2
package nl.lumc.sasc.biopet.core.report

3
import java.io.{FileOutputStream, PrintWriter, File}
4
import java.net.URL
5

6
import nl.lumc.sasc.biopet.core.{ BiopetJavaCommandLineFunction, ToolCommand }
7
import nl.lumc.sasc.biopet.core.summary.Summary
8
import org.apache.commons.io.IOUtils
9
import org.broadinstitute.gatk.utils.commandline.Input
10
import org.fusesource.scalate.{ TemplateSource, TemplateEngine }
11
12
13
14
15
16

import scala.io.Source

/**
 * Created by pjvan_thof on 3/27/15.
 */
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
trait ReportBuilderExtension extends BiopetJavaCommandLineFunction {

  val builder: ReportBuilder

  @Input(required = true)
  var summaryFile: File = _

  var outputDir: File = _

  var args: Map[String, String] = Map()

  override def beforeGraph: Unit = {
    super.beforeGraph
    jobOutputFile = new File(outputDir, ".report.log.out")
    javaMainClass = builder.getClass.getName.takeWhile(_ != '$')
  }

  override def commandLine: String = {
    super.commandLine +
      required("--summary", summaryFile) +
      required("--outputDir", outputDir) +
      args.map(x => required(x._1, x._2)).mkString
  }
}

42
43
trait ReportBuilder extends ToolCommand {

44
  case class Args(summary: File = null, outputDir: File = null, pageArgs: Map[String, String] = Map()) extends AbstractArgs
45
46

  class OptParser extends AbstractOptParser {
47
    opt[File]('s', "summary") required () maxOccurs 1 valueName "<file>" action { (x, c) =>
48
49
      c.copy(summary = x)
    }
50
    opt[File]('o', "outputDir") required () maxOccurs 1 valueName "<file>" action { (x, c) =>
51
52
      c.copy(outputDir = x)
    }
53
54
55
    opt[Map[String, String]]('a', "args") action { (x, c) =>
      c.copy(pageArgs = c.pageArgs ++ x)
    }
56
57
58
59
60
61
62
63
  }

  private var setSummary: Summary = _

  final def summary = setSummary

  def pageArgs: Map[String, Any] = Map()

Peter van 't Hof's avatar
Peter van 't Hof committed
64
65
66
  private var done = 0
  private var total = 0

67
68
69
70
71
72
73
74
75
  def main(args: Array[String]): Unit = {
    logger.info("Start")

    val argsParser = new OptParser
    val cmdArgs: Args = argsParser.parse(args, Args()) getOrElse sys.exit(1)

    require(cmdArgs.outputDir.exists(), "Output dir does not exist")
    require(cmdArgs.outputDir.isDirectory, "Output dir is not a directory")

Peter van 't Hof's avatar
Peter van 't Hof committed
76
    logger.info("Write Base files")
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94

    /**
     * Copying out the static files from this
     * */

    val resourcePath: String = "/nl/lumc/sasc/biopet/core/report/ext/"

    val externalDir = new File(cmdArgs.outputDir, "ext")
    externalDir.mkdirs()

    val uri: URL = getClass.getResource(resourcePath)
    val dir: File = new File( uri.toURI )

    for ( srcFile <- dir.listFiles ) {

      logger.info(srcFile.getPath)

      if (srcFile.isDirectory) {
95
        val newPath: String = srcFile.getAbsolutePath.split(resourcePath).last
96
97
98
99
100
101
        val workDir = new File(externalDir, newPath)
        workDir.mkdirs()
        logger.info("Writing to " + workDir.getAbsolutePath)

        for (f <- srcFile.listFiles()) {
          var newFilePath: String = f.getAbsolutePath.split(resourcePath+ newPath).last
102
          val resourceSrcPath: File = new File( resourcePath, newPath+"/"+newFilePath )
103

104
105
          val is = getClass.getResourceAsStream(resourceSrcPath.getPath)
          val os = new FileOutputStream(new File(workDir, newFilePath).getAbsolutePath)
106

107
108
          org.apache.commons.io.IOUtils.copy(is, os)
          os.close()
109
110
111
        }
      }
    }
112

Peter van 't Hof's avatar
Peter van 't Hof committed
113
    logger.info("Parsing summary")
114
115
    setSummary = new Summary(cmdArgs.summary)

Peter van 't Hof's avatar
Peter van 't Hof committed
116
117
118
    total = countPages(indexPage)
    logger.info(total + " pages to be generated")

Peter van 't Hof's avatar
Peter van 't Hof committed
119
    logger.info("Generate pages")
120
    generatePage(summary, indexPage, cmdArgs.outputDir,
121
122
      args = pageArgs ++ cmdArgs.pageArgs ++
        Map("summary" -> summary, "reportName" -> reportName, "indexPage" -> indexPage))
123

Peter van 't Hof's avatar
Peter van 't Hof committed
124
    logger.info(done + " Done")
125
126
127
128
129
130
  }

  def indexPage: ReportPage

  def reportName: String

Peter van 't Hof's avatar
Peter van 't Hof committed
131
132
133
134
  def countPages(page: ReportPage): Int = {
    page.subPages.map(x => countPages(x._2)).fold(1)(_ + _)
  }

135
136
137
138
139
140
  def generatePage(summary: Summary,
                   page: ReportPage,
                   outputDir: File,
                   path: List[String] = Nil,
                   args: Map[String, Any] = Map()): Unit = {

Peter van 't Hof's avatar
Peter van 't Hof committed
141
142
    val pageOutputDir = new File(outputDir, path.mkString(File.separator))
    pageOutputDir.mkdirs()
143
144
145
146
147
148
149
    val rootPath = "./" + Array.fill(path.size)("../").mkString("")
    val pageArgs = args ++ page.args ++
      Map("page" -> page,
        "path" -> path,
        "outputDir" -> pageOutputDir,
        "rootPath" -> rootPath
      )
150

Peter van 't Hof's avatar
Peter van 't Hof committed
151
152
153
154
    val output = ReportBuilder.renderTemplate("/nl/lumc/sasc/biopet/core/report/main.ssp",
      pageArgs ++ Map("args" -> pageArgs))

    val file = new File(pageOutputDir, "index.html")
155
156
157
158
159
    val writer = new PrintWriter(file)
    writer.println(output)
    writer.close()

    // Generating subpages
160
    for ((name, subPage) <- page.subPages.par) {
161
162
      generatePage(summary, subPage, outputDir, path ::: name :: Nil, pageArgs)
    }
Peter van 't Hof's avatar
Peter van 't Hof committed
163
164
    done += 1
    if (done % 100 == 0) logger.info(done + " Done, " + (done.toDouble / total * 100) + "%")
165
166
  }
}
Peter van 't Hof's avatar
Peter van 't Hof committed
167
168
169
170
171

object ReportBuilder {

  protected val engine = new TemplateEngine()

172
  def renderTemplate(location: String, args: Map[String, Any]): String = {
173
    engine.layout(TemplateSource.fromFile(getClass.getResource(location).getPath), args)
Peter van 't Hof's avatar
Peter van 't Hof committed
174
175
  }
}