-
Notifications
You must be signed in to change notification settings - Fork 2.3k
/
AsciiDocGenerator.java
347 lines (323 loc) · 10.6 KB
/
AsciiDocGenerator.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
/*
* Copyright (c) 2002-2016 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.doc.tools;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
import org.neo4j.graphdb.GraphDatabaseService;
/**
* Generate asciidoc-formatted documentation from HTTP requests and responses.
* The status and media type of all responses is checked as well as the
* existence of any expected headers.
*
* The filename of the resulting ASCIIDOC test file is derived from the title.
*
* The title is determined by either a JavaDoc period terminated first title
* line, the @Title annotation or the method name, where "_" is replaced by " ".
*/
public abstract class AsciiDocGenerator
{
private static final String DOCUMENTATION_END = "\n...\n";
private final Logger log = Logger.getLogger( AsciiDocGenerator.class.getName() );
protected final String title;
protected String section;
protected String description = null;
protected GraphDatabaseService graph;
protected static final String SNIPPET_MARKER = "@@";
protected Map<String, String> snippets = new HashMap<String, String>();
private static final Map<String, Integer> counters = new HashMap<String, Integer>();
public AsciiDocGenerator( final String title, final String section )
{
this.section = section;
this.title = title.replace( "_", " " );
}
public AsciiDocGenerator setGraph( GraphDatabaseService graph )
{
this.graph = graph;
return this;
}
public String getTitle()
{
return title;
}
public AsciiDocGenerator setSection(final String section)
{
this.section = section;
return this;
}
/**
* Add a description to the test (in asciidoc format). Adding multiple
* descriptions will yield one paragraph per description.
*
* @param description the description
*/
public AsciiDocGenerator description( final String description )
{
if ( description == null )
{
throw new IllegalArgumentException(
"The description can not be null" );
}
String content;
int pos = description.indexOf( DOCUMENTATION_END );
if ( pos != -1 )
{
content = description.substring( 0, pos );
}
else
{
content = description;
}
if ( this.description == null )
{
this.description = content;
}
else
{
this.description += "\n\n" + content;
}
return this;
}
protected void line( final Writer fw, final String string )
throws IOException
{
fw.append( string );
fw.append( "\n" );
}
public static Writer getFW( String dir, String title )
{
try
{
File dirs = new File( dir );
String name = title.replace( " ", "-" )
.toLowerCase() + ".asciidoc";
return getFW( dirs, name );
}
catch ( Exception e )
{
e.printStackTrace();
throw new RuntimeException( e );
}
}
public static Writer getFW( File dir, String filename )
{
try
{
if ( !dir.exists() )
{
dir.mkdirs();
}
File out = new File( dir, filename );
if ( out.exists() )
{
out.delete();
}
if ( !out.createNewFile() )
{
throw new RuntimeException( "File exists: "
+ out.getAbsolutePath() );
}
return new OutputStreamWriter( new FileOutputStream( out, false ), StandardCharsets.UTF_8 );
}
catch ( Exception e )
{
e.printStackTrace();
throw new RuntimeException( e );
}
}
public static String dumpToSeparateFile( File dir, String testId,
String content )
{
if ( content == null || content.isEmpty() )
{
throw new IllegalArgumentException( "The content can not be empty(" + content + ")." );
}
String filename = testId + ".asciidoc";
Writer writer = AsciiDocGenerator.getFW( new File( dir, "includes" ), filename );
String title = "";
char firstChar = content.charAt( 0 );
if ( firstChar == '.' || firstChar == '_' )
{
int pos = content.indexOf( '\n' );
if ( pos != -1 )
{
title = content.substring( 0, pos + 1 );
content = content.substring( pos + 1 );
}
}
try
{
writer.write( content );
}
catch ( IOException e )
{
e.printStackTrace();
}
finally
{
try
{
writer.close();
}
catch ( IOException e )
{
e.printStackTrace();
}
}
return title + "include::includes/" + filename + "[]\n";
}
public static String dumpToSeparateFileWithType( File dir, String type,
String content )
{
if ( type == null || type.isEmpty() )
{
throw new IllegalArgumentException(
"The type can not be null or empty: [" + type + "]" );
}
String key = dir.getAbsolutePath() + type;
Integer counter = counters.get( key );
if ( counter == null )
{
counter = 0;
}
counter++;
counters.put( key, counter );
String testId = type + "-" + String.valueOf( counter );
return dumpToSeparateFile( dir, testId, content );
}
public static PrintWriter getPrintWriter( String dir, String title )
{
return new PrintWriter( getFW( dir, title ) );
}
public static String getPath( Class<?> source )
{
return source.getPackage()
.getName()
.replace( ".", "/" ) + "/" + source.getSimpleName() + ".java";
}
protected String replaceSnippets( String description, File dir, String title )
{
for (String key : snippets.keySet()) {
description = replaceSnippet( description, key, dir, title );
}
if(description.contains( SNIPPET_MARKER )) {
int indexOf = description.indexOf( SNIPPET_MARKER );
String snippet = description.substring( indexOf, description.indexOf( "\n", indexOf ) );
log.severe( "missing snippet ["+snippet+"] in " + description);
}
return description;
}
private String replaceSnippet( String description, String key, File dir,
String title )
{
String snippetString = SNIPPET_MARKER + key;
if ( description.contains( snippetString + "\n" ) )
{
String include = dumpToSeparateFile( dir, title + "-" + key,
snippets.get( key ) );
description = description.replace( snippetString + "\n", include );
} else {
log.severe( "Could not find " + snippetString + "\\n in "
+ description );
}
return description;
}
/**
* Add snippets that will be replaced into corresponding.
*
* A snippet needs to be on its own line, terminated by "\n".
*
* @@snippetname placeholders in the content of the description.
*
* @param key the snippet key, without @@
* @param content the content to be inserted
*/
public void addSnippet( String key, String content )
{
snippets.put( key, content );
}
/**
* Added one or more source snippets from test sources, available from
* javadoc using
*
* @@tagName.
*
* @param source the class where the snippet is found
* @param tagNames the tag names which should be included
*/
public void addTestSourceSnippets( Class<?> source, String... tagNames )
{
for ( String tagName : tagNames )
{
addSnippet( tagName, sourceSnippet( tagName, source, "test-sources" ) );
}
}
/**
* Added one or more source snippets, available from javadoc using
*
* @@tagName.
*
* @param source the class where the snippet is found
* @param tagNames the tag names which should be included
*/
public void addSourceSnippets( Class<?> source, String... tagNames )
{
for ( String tagName : tagNames )
{
addSnippet( tagName, sourceSnippet( tagName, source, "sources" ) );
}
}
private static String sourceSnippet( String tagName, Class<?> source,
String classifier )
{
return "[snippet,java]\n" + "----\n"
+ "component=${project.artifactId}\n" + "source="
+ getPath( source ) + "\n" + "classifier=" + classifier + "\n"
+ "tag=" + tagName + "\n" + "----\n";
}
public void addGithubTestSourceLink( String key, Class<?> source,
String dir )
{
githubLink( key, source, dir, "test" );
}
public void addGithubSourceLink( String key, Class<?> source, String dir )
{
githubLink( key, source, dir, "main" );
}
private void githubLink( String key, Class<?> source, String dir,
String mainOrTest )
{
String path = "https://github.com/neo4j/neo4j/blob/{neo4j-git-tag}/";
if ( dir != null )
{
path += dir + "/";
}
path += "src/" + mainOrTest + "/java/" + getPath( source );
path += "[" + source.getSimpleName() + ".java]\n";
addSnippet( key, path );
}
}