Skip to content

Commit 43544b6

Browse files
authored
Merge pull request #100 from hauner/jimfs
support alternative `FileSystem`, ie. replace `File` with `Path`.
2 parents 9e996d6 + 64fc514 commit 43544b6

File tree

13 files changed

+330
-100
lines changed

13 files changed

+330
-100
lines changed

build.gradle

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ plugins {
1313
group 'com.github.hauner.openapi'
1414
version '1.0.0.M13'
1515

16-
sourceCompatibility = JavaVersion.VERSION_1_8
16+
sourceCompatibility = JavaVersion.VERSION_11
1717
targetCompatibility = JavaVersion.VERSION_1_8
1818

1919
ext {
@@ -58,13 +58,15 @@ compileTestGroovy {
5858

5959

6060
dependencies {
61-
implementation 'org.codehaus.groovy:groovy:2.5.4'
61+
implementation 'org.codehaus.groovy:groovy:2.5.10'
62+
implementation 'org.codehaus.groovy:groovy-nio:2.5.10'
6263
implementation 'org.jetbrains.kotlin:kotlin-stdlib'
63-
implementation 'io.swagger.parser.v3:swagger-parser:2.0.17'
64-
implementation 'org.openapi4j:openapi-parser:0.8'
64+
implementation 'io.swagger.parser.v3:swagger-parser:2.0.19'
65+
implementation 'org.openapi4j:openapi-parser:0.9'
6566
implementation 'com.google.googlejavaformat:google-java-format:1.7'
6667
compileOnly "com.github.hauner.openapi:openapi-processor-api:$processorApiVersion"
6768

69+
testImplementation 'com.google.jimfs:jimfs:1.1'
6870
testImplementation ('org.spockframework:spock-core:2.0-M2-groovy-2.5') {
6971
exclude group: 'org.codehaus.groovy'
7072
}

src/main/groovy/com/github/hauner/openapi/spring/parser/openapi4j/Parser.groovy

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,12 @@ import org.openapi4j.parser.validation.v3.OpenApi3Validator
3030
class Parser {
3131

3232
ParserOpenApi parse (String apiPath) {
33+
if (!hasScheme (apiPath)) {
34+
apiPath = "file://${apiPath}"
35+
}
3336

3437
OpenApi3 api = new OpenApi3Parser ()
35-
.parse (new File (apiPath), true)
38+
.parse (new URL (apiPath), true)
3639

3740
ValidationResults results = OpenApi3Validator
3841
.instance ()
@@ -41,4 +44,8 @@ class Parser {
4144
new OpenApi (api, results)
4245
}
4346

47+
boolean hasScheme (String path) {
48+
path.indexOf ("://") > -1
49+
}
50+
4451
}

src/main/groovy/com/github/hauner/openapi/spring/parser/swagger/Parser.groovy

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,17 @@ import io.swagger.v3.parser.core.models.ParseOptions
2222
import io.swagger.v3.parser.core.models.SwaggerParseResult
2323

2424
/**
25-
* openapi4j parser.
25+
* swagger parser.
2626
*
2727
* @author Martin Hauner
2828
*/
2929
class Parser {
3030

3131
ParserOpenApi parse (String apiPath) {
32+
if (!hasScheme (apiPath)) {
33+
apiPath = "file://${apiPath}"
34+
}
35+
3236
ParseOptions opts = new ParseOptions(
3337
// loads $refs to other files into #/components/schema and replaces the $refs to the
3438
// external files with $refs to #/components/schema.
@@ -40,4 +44,8 @@ class Parser {
4044
new OpenApi(result)
4145
}
4246

47+
boolean hasScheme (String path) {
48+
path.indexOf ("://") > -1
49+
}
50+
4351
}

src/main/groovy/com/github/hauner/openapi/spring/processor/MappingReader.groovy

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,16 @@ class MappingReader {
3737
return null
3838
}
3939

40-
String mapping = typeMappings
41-
if (isFileName (typeMappings)) {
40+
def mapping
41+
if (isUrl (typeMappings)) {
42+
mapping = new URL (typeMappings).text
43+
} else if (isFileName (typeMappings)) {
4244
mapping = new File (typeMappings).text
45+
} else {
46+
mapping = typeMappings
4347
}
4448

4549
def mapper = createYamlParser ()
46-
4750
mapper.readValue (mapping, Mapping)
4851
}
4952

@@ -61,4 +64,12 @@ class MappingReader {
6164
name.endsWith ('.yaml') || name.endsWith ('.yml')
6265
}
6366

67+
private boolean isUrl (String source) {
68+
try {
69+
new URL (source)
70+
} catch (MalformedURLException ignore) {
71+
false
72+
}
73+
}
74+
6475
}

src/main/groovy/com/github/hauner/openapi/spring/writer/ApiWriter.groovy

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ import com.google.googlejavaformat.java.Formatter
2525
import com.google.googlejavaformat.java.JavaFormatterOptions
2626
import groovy.util.logging.Slf4j
2727

28+
import java.nio.file.Files
29+
import java.nio.file.Path
30+
2831
import static com.github.hauner.openapi.support.Identifier.toClass
2932

3033
/**
@@ -40,8 +43,8 @@ class ApiWriter {
4043
DataTypeWriter dataTypeWriter
4144
StringEnumWriter enumWriter
4245

43-
File apiFolder
44-
File modelFolder
46+
Path apiFolder
47+
Path modelFolder
4548

4649
Formatter formatter
4750

@@ -69,22 +72,22 @@ class ApiWriter {
6972
createTargetFolders ()
7073

7174
api.interfaces.each {
72-
def target = new File (apiFolder, "${it.interfaceName}.java")
73-
def writer = new FileWriter(target)
75+
def target = apiFolder.resolve ("${it.interfaceName}.java")
76+
def writer = new BufferedWriter (new PathWriter(target))
7477
writeInterface (writer, it)
7578
writer.close ()
7679
}
7780

7881
api.models.objectDataTypes.each {
79-
def target = new File (modelFolder, "${it.name}.java")
80-
def writer = new FileWriter(target)
82+
def target = modelFolder.resolve ("${it.name}.java")
83+
def writer = new BufferedWriter (new PathWriter(target))
8184
writeDataType (writer, it)
8285
writer.close ()
8386
}
8487

8588
api.models.enumDataTypes.each {
86-
def target = new File (modelFolder, "${it.name}.java")
87-
def writer = new FileWriter(target)
89+
def target = modelFolder.resolve ("${it.name}.java")
90+
def writer = new BufferedWriter (new PathWriter(target))
8891
writeEnumDataType (writer, it)
8992
writer.close ()
9093
}
@@ -132,23 +135,25 @@ class ApiWriter {
132135
log.debug ('creating target folders: {}', rootPkg)
133136

134137
apiFolder = createTargetPackage (apiPkg)
135-
log.debug ('created target folder: {}', apiFolder.absolutePath)
138+
log.debug ('created target folder: {}', apiFolder.toAbsolutePath ().toString ())
136139

137140
modelFolder = createTargetPackage (modelPkg)
138-
log.debug ('created target folder: {}', modelFolder.absolutePath)
141+
log.debug ('created target folder: {}', modelFolder.toAbsolutePath ().toString ())
139142
}
140143

141-
private File createTargetPackage (String apiPkg) {
142-
def folder = new File ([options.targetDir, apiPkg].join (File.separator))
143-
if (folder.exists () && folder.isDirectory ()) {
144-
return folder
144+
private Path createTargetPackage (String apiPkg) {
145+
String root = options.targetDir
146+
if (!hasScheme (root)) {
147+
root = "file://${root}"
145148
}
146149

147-
def success = folder.mkdirs ()
148-
if (!success) {
149-
log.error ('failed to create package {}', folder)
150-
}
151-
folder
150+
def target = Path.of (new URL ([root, apiPkg].join ('/')).toURI ())
151+
Files.createDirectories (target)
152+
target
153+
}
154+
155+
private boolean hasScheme (String source) {
156+
source.indexOf ("://") > -1
152157
}
153158

154159
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright 2019-2020 the original authors
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 com.github.hauner.openapi.spring.writer
18+
19+
import java.nio.file.Files
20+
import java.nio.file.Path
21+
22+
/**
23+
* Path based Writer
24+
*
25+
* @author Martin Haner
26+
*/
27+
class PathWriter extends OutputStreamWriter {
28+
29+
PathWriter(Path target) throws IOException {
30+
super(Files.newOutputStream (target));
31+
}
32+
33+
}

src/test/groovy/com/github/hauner/openapi/spring/processor/MappingReaderSpec.groovy

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,20 @@
1616

1717
package com.github.hauner.openapi.spring.processor
1818

19+
import com.google.common.jimfs.Configuration
20+
import com.google.common.jimfs.Jimfs
1921
import org.junit.Rule
2022
import org.junit.rules.TemporaryFolder
23+
import spock.lang.Shared
2124
import spock.lang.Specification
2225

26+
import java.nio.file.FileSystem
27+
2328
class MappingReaderSpec extends Specification {
2429

30+
@Shared
31+
FileSystem fs = Jimfs.newFileSystem (Configuration.unix ())
32+
2533
@Rule
2634
TemporaryFolder folder
2735

@@ -37,30 +45,51 @@ class MappingReaderSpec extends Specification {
3745
yaml << [null, ""]
3846
}
3947

40-
void "reads mapping from file" () {
48+
void "reads mapping from url" () {
49+
def yaml = """\
50+
openapi-processor-spring: v1.0
51+
52+
map:
53+
types:
54+
- from: array
55+
to: java.util.Collection
56+
"""
57+
58+
def yamlFile = fs.getPath ('mapping.yaml')
59+
yamlFile.text = yaml
60+
61+
when:
62+
def reader = new MappingReader()
63+
def mapping = reader.read (yamlFile.toUri ().toURL ().toString ())
64+
65+
then:
66+
mapping
67+
}
68+
69+
void "reads mapping from local file if the scheme is missing" () {
4170
def yaml = """\
42-
openapi-generatr-spring: v1.0
71+
openapi-processor-spring: v1.0
4372
4473
map:
4574
types:
4675
- from: array
4776
to: java.util.Collection
4877
"""
4978

50-
def yamlFile = folder.newFile ("openapi-generatr-spring.yaml")
79+
def yamlFile = folder.newFile ('mapping.yaml')
5180
yamlFile.text = yaml
5281

5382
when:
5483
def reader = new MappingReader()
55-
def mapping = reader.read (yamlFile.absolutePath)
84+
def mapping = reader.read (yamlFile.toString ())
5685

5786
then:
5887
mapping
5988
}
6089

6190
void "reads mapping from string" () {
6291
def yaml = """\
63-
openapi-generatr-spring: v1.0
92+
openapi-processor-spring: v1.0
6493
6594
map:
6695
types:

src/test/groovy/com/github/hauner/openapi/spring/writer/ApiWriterSpec.groovy

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ class ApiWriterSpec extends Specification {
4747
)
4848

4949
when:
50-
new ApiWriter (opts, Stub (InterfaceWriter), null, null).write (new Api())
50+
new ApiWriter (opts, Stub (InterfaceWriter), null, null)
51+
.write (new Api())
5152

5253
then:
5354
def api = new File([opts.targetDir, 'com', 'github', 'hauner', 'openapi', 'api'].join(File.separator))
Lines changed: 9 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2019 the original authors
2+
* Copyright 2019-2020 the original authors
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,48 +17,23 @@
1717
package com.github.hauner.openapi.processor
1818

1919
import com.github.hauner.openapi.spring.parser.ParserType
20+
import org.junit.Test
2021
import org.junit.runner.RunWith
2122
import org.junit.runners.Parameterized
2223

2324
/**
2425
* using Junit so IDEA adds a "<Click to see difference>" when using assertEquals().
2526
*/
26-
2727
@RunWith(Parameterized)
2828
class ProcessorEndToEndTest extends ProcessorTestBase {
2929

30-
static def testSets = [
31-
'bean-validation',
32-
'endpoint-exclude',
33-
'method-operation-id',
34-
'no-response-content',
35-
'params-additional',
36-
'params-complex-data-types',
37-
'params-enum',
38-
'params-simple-data-types',
39-
'params-request-body',
40-
'params-request-body-multipart-form-data',
41-
'params-path-simple-data-types',
42-
'params-spring-pageable-mapping',
43-
'ref-into-another-file',
44-
'ref-loop',
45-
'response-array-data-type-mapping',
46-
'response-complex-data-types',
47-
'response-content-multiple',
48-
'response-content-single',
49-
'response-result-mapping',
50-
'response-simple-data-types',
51-
'response-single-multi-mapping',
52-
'schema-composed'
53-
]
54-
5530
@Parameterized.Parameters(name = "{0}")
5631
static Collection<TestSet> sources () {
57-
def swagger = testSets.collect {
32+
def swagger = TestSet.testSets.collect {
5833
new TestSet (name: it, parser: ParserType.SWAGGER)
5934
}
6035

61-
def openapi4j = testSets.collect {
36+
def openapi4j = TestSet.testSets.collect {
6237
new TestSet (name: it, parser: ParserType.OPENAPI4J)
6338
}
6439

@@ -69,4 +44,9 @@ class ProcessorEndToEndTest extends ProcessorTestBase {
6944
super (testSet)
7045
}
7146

47+
@Test
48+
void "native - processor creates expected files for api set "() {
49+
runOnNativeFileSystem ()
50+
}
51+
7252
}

0 commit comments

Comments
 (0)