Skip to content

Instantly share code, notes, and snippets.

@sns-seb
Created February 6, 2019 15:35
Show Gist options
  • Save sns-seb/fae894ada2e53585ae52c08a50e8c75f to your computer and use it in GitHub Desktop.
Save sns-seb/fae894ada2e53585ae52c08a50e8c75f to your computer and use it in GitHub Desktop.
/*
* SonarQube
* Copyright (C) 2009-2019 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.ce.task;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Consumer;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.junit.Test;
import static java.lang.String.format;
import static org.assertj.core.api.Assertions.assertThat;
public class ReadEsAsciiDoc {
@Test
public void readit() throws IOException {
Map<String, Map<ChangeType, List<DataInfo>>> output = read(
Paths.get("/home/sebastienl/DEV/elasticsearch/docs/reference/release-notes/6.6.asciidoc"),
Paths.get("/home/sebastienl/DEV/elasticsearch/docs/reference/release-notes/6.5.asciidoc"),
Paths.get("/home/sebastienl/DEV/elasticsearch/docs/reference/release-notes/6.4.asciidoc"),
Paths.get("/home/sebastienl/DEV/elasticsearch/docs/reference/release-notes/6.3.asciidoc"),
Paths.get("/home/sebastienl/DEV/elasticsearch/docs/reference/release-notes/6.2.asciidoc"),
Paths.get("/home/sebastienl/DEV/elasticsearch/docs/reference/release-notes/6.1.asciidoc"),
Paths.get("/home/sebastienl/DEV/elasticsearch/docs/reference/release-notes/6.0.asciidoc")
);
assertThat(output).isNotEmpty();
String pattern = "\"%s\",\"%s\",\"%s\",\"%s\",\"%s\"";
List<String> csvLines = new ArrayList<>();
csvLines.add(format(pattern, "version", "changeType", "category", "status", "description"));
output.forEach((version, map) -> {
csvLines.add(format(pattern, version, "", "", "", ""));
map.forEach(((changeType, dataInfos) -> {
dataInfos.forEach(dataInfo -> {
String description = dataInfo.info + (dataInfo.subInfo == null ? "" : dataInfo.subInfo);
csvLines.add(format(pattern, version, changeType, dataInfo.category, "", description));
});
}));
});
Files.write(Paths.get("/tmp/es_changes.csv"), csvLines);
}
private Map<String, Map<ChangeType, List<DataInfo>>> read(Path... inputs) throws IOException {
EsVersionAsciidocReader reader = new EsVersionAsciidocReader();
for (Path input : inputs) {
Files.lines(input, Charset.defaultCharset()).forEach(reader);
}
reader.flush(false);
return reader.output;
}
private enum ChangeType {
BREAKING_CHANGES("Breaking Changes"),
JAVA_BREAKING_CHANGES("Breaking Java Changes"),
IGNORED(null);
@CheckForNull
private final String text;
ChangeType(@Nullable String text) {
this.text = text;
}
public static Optional<ChangeType> fromLine(String line) {
String prefix = "=== ";
if (!line.startsWith(prefix)) {
return Optional.empty();
}
Optional<ChangeType> supported = Arrays.stream(values())
.filter(t -> t.text != null)
.filter(t -> line.equalsIgnoreCase(prefix + t.text))
.findFirst();
if (supported.isPresent()) {
return supported;
}
return Optional.of(IGNORED);
}
}
private static final class DataInfo {
private final String category;
private final String info;
@CheckForNull
private final String subInfo;
private DataInfo(String category, String info, @Nullable String subInfo) {
this.category = category;
this.info = info;
this.subInfo = subInfo;
}
@Override
public String toString() {
if (subInfo == null) {
return category + ":: " + info;
}
return category + " :: " + info + " : " + subInfo;
}
}
private static class EsVersionAsciidocReader implements Consumer<String> {
private final Map<String, Map<ChangeType, List<DataInfo>>> output = new LinkedHashMap<>();
private int lineNumber = 0;
private String currentVersion = null;
private ChangeType currentChangeType = null;
private String currentCategory = null;
private String currentInfo = null;
private String currentSubInfo = null;
@Override
public void accept(String line) {
lineNumber++;
if (isAnchorOrFormatting(line)) {
flush(false);
return;
}
Optional<String> version = readVersion(line);
if (version.isPresent()) {
flush(false);
currentVersion = version.get();
currentChangeType = null;
currentCategory = null;
currentInfo = null;
currentSubInfo = null;
return;
}
Optional<ChangeType> changeType = currentVersion == null ? Optional.empty() : ChangeType.fromLine(line);
if (changeType.isPresent()) {
currentChangeType = changeType.filter(t -> t != ChangeType.IGNORED).orElse(null);
currentCategory = null;
currentInfo = null;
currentSubInfo = null;
return;
}
Optional<String> category = currentChangeType == null ? Optional.empty() : readCategory(line);
if (category.isPresent()) {
currentCategory = category.get();
currentInfo = null;
currentSubInfo = null;
return;
}
Optional<String> info = currentCategory == null ? Optional.empty() : readInfo(line);
if (info.isPresent()) {
flush(false);
currentInfo = info.get();
currentSubInfo = null;
printData();
return;
}
Optional<String> subInfo = currentInfo == null ? Optional.empty() : readSubInfo(line);
if (subInfo.isPresent()) {
flush(true);
currentSubInfo = subInfo.get();
printData();
return;
}
if (!line.isEmpty()) {
if (currentSubInfo != null) {
currentSubInfo += " " + line;
printData();
return;
}
if (currentInfo != null) {
currentInfo += " " + line;
printData();
return;
}
} else {
flush(false);
}
System.err.println(format("??? %s : %s : %s : %s", currentVersion, currentChangeType, currentCategory, line));
}
private void flush(boolean onsubInfoOnly) {
if (currentVersion != null && currentChangeType != null && currentCategory != null && currentInfo != null
&& (!onsubInfoOnly || currentSubInfo != null)) {
output.compute(currentVersion,
(version, existingMap) -> {
Map<ChangeType, List<DataInfo>> value = existingMap == null ? new LinkedHashMap<>() : existingMap;
value.compute(currentChangeType,
((changeType, existingList) -> {
List<DataInfo> list = existingList == null ? new ArrayList<>() : existingList;
list.add(new DataInfo(currentCategory, currentInfo, currentSubInfo));
return list;
}));
return value;
});
if (!onsubInfoOnly) {
currentInfo = null;
}
currentSubInfo = null;
}
}
private void printData() {
System.out.println(format("(%s) DATA %s : %s : %s : %s : %s", lineNumber, currentVersion, currentChangeType, currentCategory, currentInfo, currentSubInfo));
}
private Optional<String> readSubInfo(String line) {
if (line.startsWith("** ")) {
return Optional.of(line.substring("** ".length()));
}
return Optional.empty();
}
private Optional<String> readInfo(String line) {
if (line.startsWith("* ")) {
return Optional.of(line.substring(2));
}
return Optional.empty();
}
private boolean isAnchorOrFormatting(String line) {
return line.startsWith("[");
}
private Optional<String> readVersion(String line) {
String prefix = "== {es} version ";
if (line.startsWith(prefix)) {
return Optional.of(line.substring(prefix.length()));
}
return Optional.empty();
}
private Optional<String> readCategory(String line) {
if (line.endsWith("::")) {
return Optional.of(line.substring(0, line.length() - "::".length()));
}
return Optional.empty();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment