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

Peter van 't Hof's avatar
Peter van 't Hof committed
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

Peter van 't Hof's avatar
Peter van 't Hof committed
12
13
import scala.concurrent.Await
import scala.concurrent.duration.Duration
14
15
16
17
18
import scala.io.Source

/**
 * Created by pjvan_thof on 3/27/15.
 */
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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
  }
}

44
45
trait ReportBuilder extends ToolCommand {

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

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

  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
66
67
68
  private var done = 0
  private var total = 0

69
70
71
72
73
74
75
76
77
  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
78
    logger.info("Write Base files")
79
80
81

    /**
     * Copying out the static files from this
Peter van 't Hof's avatar
Peter van 't Hof committed
82
     */
83
84
85
86
87
88
89

    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)
Peter van 't Hof's avatar
Peter van 't Hof committed
90
    val dir: File = new File(uri.toURI)
91

Peter van 't Hof's avatar
Peter van 't Hof committed
92
    for (srcFile <- dir.listFiles) {
93
94
95
96

      logger.info(srcFile.getPath)

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

        for (f <- srcFile.listFiles()) {
Peter van 't Hof's avatar
Peter van 't Hof committed
103
104
          val newFilePath: String = f.getAbsolutePath.split(resourcePath + newPath).last
          val resourceSrcPath: File = new File(resourcePath, newPath + "/" + newFilePath)
105

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

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

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

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

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

Peter van 't Hof's avatar
Peter van 't Hof committed
126
    logger.info(jobs + " Done")
127
128
129
130
131
132
  }

  def indexPage: ReportPage

  def reportName: String

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

137
138
139
140
  def generatePage(summary: Summary,
                   page: ReportPage,
                   outputDir: File,
                   path: List[String] = Nil,
Peter van 't Hof's avatar
Peter van 't Hof committed
141
                   args: Map[String, Any] = Map()): Int = {
142

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

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

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

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

object ReportBuilder {

  protected val engine = new TemplateEngine()

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