• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package writer.files
18 
19 import parser.LOG_NAME
20 import parser.config
21 import parser.files.AbstractFileParser
22 import parser.files.InterfaceFileParser
23 import writer.getDescSummaryText
24 import writer.getOutPath
25 import java.io.File
26 import java.nio.file.Path
27 import java.nio.file.Paths
28 
29 data class EntryData(val fullName: String, //package.BaseName
30                      val baseName: String,
31                      val packageName: String,
32                      val packageVersion: Float,
33                      val summary: String,
34                      val relPath: Path)
35 
36 class IndexFileWriter : AbstractFileWriter() {
37 
38     override val baseName = "index"
39     override val templateResource = "/resources/template/${this.baseName}.html"
40     override val path: Path by lazy { Paths.get("${config.outDir}${File.separator}${this.baseName}.html") }
41 
42     private val entries = mutableListOf<EntryData>()
43 
44     fun addEntry(parser: AbstractFileParser) {
45         val summaryStr = when (parser) {
46             is InterfaceFileParser -> getDescSummaryText(parser.description)
47             else -> ""
48         }
49         entries.add(EntryData(
50                 fullName = "${parser.packageName}.${parser.name}",
51                 baseName = parser.name,
52                 packageName = parser.packageName,
53                 packageVersion = parser.packageVersion,
54                 summary = summaryStr,
55                 relPath = config.outDir.relativize(getOutPath(parser, config.outDir))
56         ))
57     }
58 
59     override fun printInfo() {
60         super.printInfo()
61         println( "IndexFileWriter:")
62         println("  entries: ${this.entries.size}")
63     }
64 
65     /*
66      * HTML index file
67      */
68 
69     override fun replaceVars() {
70         replaceVar("title", "Index")
71 
72         replaceVar("entries") {
73             val sb = StringBuilder()
74             if (entries.isNotEmpty()) {
75                 entries.sortWith(EntryNameComparator())
76                 sb.append(buildEntryTable())
77             }
78             sb.toString()
79         }
80     }
81 
82     private fun buildEntryTable(): String {
83         return """
84 <table>
85   <tr>
86     <th>Entry</th>
87     <th>Version</th>
88     <th>Summary</th>
89   </tr>
90 ${entries.map { buildClassEntry(it) }.joinToString("\n")}
91 </table>
92 """.trim()
93     }
94 
95     private fun buildClassEntry(entry: EntryData): String {
96         return """
97 <tr>
98   <td>
99 <a href="${entry.relPath}">${entry.fullName}</a>
100   </td>
101   <td>
102 ${entry.packageVersion}
103   </td>
104   <td>
105 ${entry.summary}
106   </td>
107 </tr>
108 """.trim()
109     }
110 
111     private class EntryNameComparator : Comparator<EntryData> {
112         override fun compare(entry1: EntryData, entry2: EntryData): Int {
113             return if (entry1.fullName != entry2.fullName) {
114                 //sort on name first, alphabetic
115                 when {
116                     entry1.fullName < entry2.fullName -> -1
117                     entry1.fullName > entry2.fullName -> 1
118                     else -> 0
119                 }
120             } else {
121                 //if same name, reverse sort on pkg version (highest first)
122                 when {
123                     entry1.packageVersion < entry2.packageVersion -> 1
124                     entry1.packageVersion > entry2.packageVersion -> -1
125                     else -> 0
126                 }
127             }
128         }
129     }
130 
131     /*
132      * YAML toc file
133      */
134 
135     private val tocFileName = "_book.yaml"
136     private val tocFileRelPath = "/reference/hidl"
137     private val tocOutPath: Path by lazy { Paths.get("${config.outDir}${File.separator}${this.tocFileName}") }
138 
139     //write toc yaml file after html index
140     override fun onWrite() {
141         super.onWrite()
142         if (!config.lintMode) {
143             val fp = tocOutPath.toFile()
144             fp.bufferedWriter().use {
145                 it.write(buildTocHeader())
146                 it.write(buildTocEntries(collectPackages()))
147             }
148             if (!fp.isFile) throw FileSystemException(fp, reason = "Error writing file")
149             println("$LOG_NAME Wrote toc: $tocOutPath")
150         }
151     }
152 
153     private fun buildTocHeader(): String {
154         return """
155 # Generated by hidl-doc
156 toc:
157 - title: Index
158   path: $tocFileRelPath
159 """.trimStart()
160     }
161 
162     private fun buildTocEntries(pkgEntries: Map<String, List<EntryData>>): String {
163         val sb = StringBuilder()
164 
165         for ((pkgName, entryList) in pkgEntries) {
166             sb.append("- title: $pkgName\n  section:\n")
167 
168             entryList.forEach { entry ->
169                 sb.append("  - title: ${entry.baseName} @${entry.packageVersion}\n")
170                 sb.append("    path: ${tocFileRelPath}/${entry.relPath}\n")
171             }
172         }
173         return sb.toString()
174     }
175 
176     private fun collectPackages(): Map<String, List<EntryData>> {
177         val pkgEntries = mutableMapOf<String, MutableList<EntryData>>()
178 
179         this.entries.forEach { entry ->
180             if (pkgEntries.containsKey(entry.packageName)) {
181                 pkgEntries[entry.packageName]!!.add(entry)
182             } else {
183                 pkgEntries[entry.packageName] = mutableListOf(entry)
184             }
185         }
186         //sort on package name. entries *should* already be sorted
187         return pkgEntries.toSortedMap()
188     }
189 }