Skip to content

Commit f7c0aa5

Browse files
authored
refactor: Object-oriented AggregateSnippets script (#116)
1 parent ea2ca0b commit f7c0aa5

File tree

2 files changed

+155
-49
lines changed

2 files changed

+155
-49
lines changed

SNIPPETS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ This file was generated by running [AggregateSnippets.java](src/main/java/Aggreg
2020
- [**Verify**](#verify)
2121
- [**Verify v2**](#verify-v2)
2222
- [**Voice**](#voice)
23+
2324
## Initialize
2425
### Application Auth With Key Contents
2526

src/main/java/AggregateSnippets.java

Lines changed: 154 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,190 @@
1+
/*
2+
* Copyright 2025 Vonage
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy
5+
* of this software and associated documentation files (the "Software"), to deal
6+
* in the Software without restriction, including without limitation the rights
7+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
* copies of the Software, and to permit persons to whom the Software is
9+
* furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in
12+
* all copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20+
* THE SOFTWARE.
21+
*/
22+
123
import java.io.File;
224
import java.io.IOException;
325
import java.nio.file.Files;
426
import java.nio.file.Path;
527
import java.nio.file.Paths;
628
import java.nio.file.StandardOpenOption;
7-
import java.util.Objects;
29+
import java.util.*;
30+
31+
public final class AggregateSnippets {
832

9-
public class AggregateSnippets {
10-
public static void main(String[] args) throws Throwable {
33+
public static void main(String... args) throws Throwable {
1134
final var repoRoot = Paths.get("").toAbsolutePath();
1235
final var snippetsSrcRoot = repoRoot.resolve("src/main/java/com/vonage/quickstart");
13-
final var classFileName = "AggregateSnippets.java";
14-
var sb = new StringBuilder(1 << 17)
36+
final var aggregator = new AggregateSnippets(snippetsSrcRoot);
37+
aggregator.computeContents();
38+
aggregator.saveContentsToFile(repoRoot.resolve("SNIPPETS.md"));
39+
if (args.length > 0) {
40+
aggregator.saveLineNumbersToCsv(Paths.get(args[0]));
41+
}
42+
}
43+
44+
45+
public record CodeSnippetFileInfo(
46+
Path file,
47+
int mainStartIndex, int mainEndIndex,
48+
int clientStartIndex, int clientEndIndex
49+
) { }
50+
51+
private StringBuilder sb;
52+
private final Path snippetsSrcRoot;
53+
private Collection<CodeSnippetFileInfo> snippetFiles;
54+
55+
public AggregateSnippets(Path snippetsSrcRoot) {
56+
this.snippetsSrcRoot = Objects.requireNonNull(snippetsSrcRoot);
57+
}
58+
59+
private void checkComputed() {
60+
if (sb == null || sb.isEmpty()) {
61+
throw new IllegalStateException("Contents not computed yet.");
62+
}
63+
}
64+
65+
public Collection<CodeSnippetFileInfo> getLineNumbers() {
66+
checkComputed();
67+
return snippetFiles;
68+
}
69+
70+
public String getContents() {
71+
checkComputed();
72+
return sb.toString();
73+
}
74+
75+
public void saveContentsToFile(Path destPath) throws IOException {
76+
Files.writeString(destPath, getContents(), StandardOpenOption.CREATE);
77+
}
78+
79+
public void saveLineNumbersToCsv(Path destPath) throws IOException {
80+
checkComputed();
81+
try (var writer = Files.newBufferedWriter(destPath, StandardOpenOption.CREATE)) {
82+
writer.write("File,MainStart,MainEnd,ClientStart,ClientEnd\n");
83+
for (var metadata : snippetFiles) {
84+
writer.write(
85+
metadata.file.getFileName() + "," +
86+
metadata.mainStartIndex + "," +
87+
metadata.mainEndIndex + "," +
88+
metadata.clientStartIndex + "," +
89+
metadata.clientEndIndex + "\n"
90+
);
91+
}
92+
}
93+
}
94+
95+
public void computeContents() throws IOException {
96+
snippetFiles = new ArrayList<>(256);
97+
final String classFileName = getClass().getSimpleName() + ".java";
98+
sb = new StringBuilder(1 << 17)
1599
.append("# Vonage Java SDK Code Snippets\n")
16100
.append("Here are all the snippets in this repository.\n")
17101
.append("This file was generated by running [").append(classFileName)
18102
.append("](src/main/java/").append(classFileName)
19103
.append(") from the root of the repository.")
20104
.append("\n\n## Contents");
21105

22-
var allDirs = Files.list(snippetsSrcRoot)
23-
.filter(Files::isDirectory)
106+
var allDirs = getAllDirsSorted();
107+
108+
for (var file : allDirs) {
109+
var title = toHeadingTitle(file.getName());
110+
sb.append("\n- [**").append(title).append("**](#")
111+
.append(title.toLowerCase().replace(' ', '-')).append(")");
112+
}
113+
sb.append("\n\n");
114+
115+
for (var file : allDirs) {
116+
appendSnippetContent(file, 2);
117+
}
118+
}
119+
120+
private List<File> getAllDirsSorted() {
121+
try (var pathStream = Files.list(snippetsSrcRoot)) {
122+
return pathStream.filter(Files::isDirectory)
24123
.map(Path::toFile)
25124
.sorted((f1, f2) -> {
26125
if (isInitialize(f1)) return -1;
27126
if (isInitialize(f2)) return 1;
28127
return f1.getName().compareToIgnoreCase(f2.getName());
29128
})
30129
.toList();
130+
}
131+
catch (IOException ex) {
132+
System.err.println("Could not read "+snippetsSrcRoot+": " + ex.getMessage());
133+
return List.of();
134+
}
135+
}
31136

32-
for (var file : allDirs) {
33-
var title = toHeadingTitle(file.getName());
34-
sb.append("\n- [**").append(title).append("**](#")
35-
.append(title.toLowerCase().replace(' ', '-')).append(")");
137+
private void appendSnippetContent(File path, int level) throws IOException {
138+
var fileName = path.getName();
139+
if (path.isFile()) {
140+
fileName = fileName.substring(0, fileName.lastIndexOf('.'));
141+
}
142+
if (fileName.trim().length() < 3) return;
143+
144+
sb.append("#".repeat(level)).append(' ').append(toHeadingTitle(fileName)).append('\n');
145+
if (path.isDirectory()) {
146+
for (var file : Objects.requireNonNull(path.listFiles())) {
147+
appendSnippetContent(file, level + 1);
148+
}
36149
}
37-
sb.append("\n");
150+
else if (level > 2 && path.getName().endsWith(".java")) {
151+
final String fileContent = Files.readString(path.toPath()),
152+
clientInitEndStr = ".build();\n\n",
153+
clientInitStartStr = "VonageClient client";
38154

39-
for (var file : allDirs) {
40-
appendSnippetContent(sb, file, 2);
155+
final int clientInitStartIndex = fileContent.indexOf(clientInitStartStr) - 8,
156+
clientInitEndIndex = fileContent.indexOf(clientInitEndStr) + 11,
157+
endIndex = fileContent.lastIndexOf('}', fileContent.lastIndexOf('}') - 1) - 1,
158+
startIndex = Math.min(endIndex, clientInitStartIndex > 0 ?
159+
(isInitialize(path.getParentFile()) ? clientInitStartIndex : clientInitEndIndex) :
160+
fileContent.indexOf('{', fileContent.indexOf('{') + 1) + 2
161+
);
162+
163+
final String nugget = fileContent.substring(startIndex, endIndex)
164+
.stripTrailing().stripIndent().replace("\t", " ");
165+
166+
sb.append("\n```java\n").append(nugget).append("\n```\n");
167+
168+
boolean standalone = clientInitEndIndex < 12;
169+
snippetFiles.add(new CodeSnippetFileInfo(path.toPath(),
170+
lineNumberFromIndex(fileContent, startIndex) + 1,
171+
lineNumberFromIndex(fileContent, endIndex),
172+
standalone ? -1 : lineNumberFromIndex(fileContent, clientInitStartIndex) + 1,
173+
standalone ? -1 : lineNumberFromIndex(fileContent, clientInitEndIndex)
174+
));
41175
}
176+
}
42177

43-
var destPath = repoRoot.resolve("SNIPPETS.md");
44-
Files.deleteIfExists(destPath);
45-
Files.writeString(destPath, sb.toString(), StandardOpenOption.CREATE_NEW);
178+
private static int lineNumberFromIndex(String content, int index) {
179+
if (index < 0) return -1;
180+
return content.substring(0, index).split("\n").length;
46181
}
47182

48-
static boolean isInitialize(File file) {
183+
private static boolean isInitialize(File file) {
49184
return file.getName().equals("initialize");
50185
}
51186

52-
static String toHeadingTitle(String title) {
187+
private static String toHeadingTitle(String title) {
53188
var acronyms = new String[]{
54189
"jwt", "id", "uuid", "url", "sim",
55190
"sms", "rcs", "mms", "psd2", "dlr", "cnam",
@@ -73,34 +208,4 @@ static String toHeadingTitle(String title) {
73208
}
74209
return result;
75210
}
76-
77-
static void appendSnippetContent(StringBuilder contentBuilder, File path, int level) throws IOException {
78-
var fileName = path.getName();
79-
if (path.isFile()) {
80-
fileName = fileName.substring(0, fileName.lastIndexOf('.'));
81-
}
82-
if (fileName.trim().length() < 3) return;
83-
84-
contentBuilder.append("#".repeat(level)).append(' ').append(toHeadingTitle(fileName)).append('\n');
85-
if (path.isDirectory()) {
86-
for (var file : Objects.requireNonNull(path.listFiles())) {
87-
appendSnippetContent(contentBuilder, file, level + 1);
88-
}
89-
}
90-
else if (level > 2 && path.getName().endsWith(".java")) {
91-
final var fileContent = Files.readString(path.toPath());
92-
final var clientInitEndStr = ".build();\n\n";
93-
final var clientInitStartStr = "VonageClient client";
94-
final int endIndex = fileContent.lastIndexOf('}', fileContent.lastIndexOf('}') - 1) - 1;
95-
final int startIndex = Math.min(endIndex, fileContent.contains(clientInitStartStr) ?
96-
(isInitialize(path.getParentFile()) ? fileContent.indexOf(clientInitStartStr) - 8 :
97-
fileContent.indexOf(clientInitEndStr) + clientInitEndStr.length()) :
98-
fileContent.indexOf('{', fileContent.indexOf('{') + 1) + 2
99-
);
100-
101-
final var nugget = fileContent.substring(startIndex, endIndex)
102-
.stripTrailing().stripIndent().replace("\t", " ");
103-
contentBuilder.append("\n```java\n").append(nugget).append("\n```\n");
104-
}
105-
}
106211
}

0 commit comments

Comments
 (0)