Skip to content

Commit 18373aa

Browse files
committed
feat: add base structure
1 parent 57288fe commit 18373aa

File tree

10 files changed

+226
-0
lines changed

10 files changed

+226
-0
lines changed

internal/load/contentLoader.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package load
2+
3+
import (
4+
"context"
5+
"errors"
6+
"github.com/rog-golang-buddies/internal/model"
7+
)
8+
9+
//ContentLoader loads content by url
10+
type ContentLoader interface {
11+
Load(ctx context.Context, url string) (*model.FileResource, error)
12+
}
13+
14+
type ContentLoaderImpl struct {
15+
}
16+
17+
func (cl *ContentLoaderImpl) Load(ctx context.Context, url string) (*model.FileResource, error) {
18+
//load content by url
19+
return nil, errors.New("not implemented")
20+
}
21+
22+
func NewContentLoader() ContentLoader {
23+
return &ContentLoaderImpl{}
24+
}

internal/model/apiSpecDoc.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package model
2+
3+
type ApiSpecDoc struct {
4+
}

internal/model/fileResource.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package model
2+
3+
//FileResource representation of file resource
4+
type FileResource struct {
5+
//File name if exists, else empty
6+
Name string
7+
8+
//Original link to file
9+
Link string
10+
11+
//File content
12+
Content []byte
13+
}

internal/model/fileType.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package model
2+
3+
type AsdFileType int
4+
5+
const (
6+
Undefined AsdFileType = iota
7+
YamlOpenApi
8+
JsonOpenAPI
9+
)

internal/parse/converter.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package parse
2+
3+
import (
4+
"errors"
5+
"github.com/rog-golang-buddies/internal/model"
6+
)
7+
8+
//Converter converts file data to API specification document using specific file type
9+
type Converter interface {
10+
Convert(content []byte, fileType model.AsdFileType) (*model.ApiSpecDoc, error)
11+
}
12+
13+
type ConverterImpl struct {
14+
//For instance, we may have a map to hold parsers for different types. And populate it in NewConverter
15+
parsers map[model.AsdFileType]Parser
16+
}
17+
18+
func (c *ConverterImpl) Convert(content []byte, fileType model.AsdFileType) (*model.ApiSpecDoc, error) {
19+
//Just example
20+
parser, ok := c.parsers[fileType]
21+
if !ok {
22+
return nil, errors.New("file type not supported")
23+
}
24+
apiSpec, err := parser.parse(content)
25+
if err != nil {
26+
return nil, err
27+
}
28+
29+
return apiSpec, nil
30+
}
31+
32+
func NewConverter(parsers []Parser) Converter {
33+
parsersMap := make(map[model.AsdFileType]Parser)
34+
for _, parser := range parsers {
35+
parsers[parser.getType()] = parser
36+
}
37+
return &ConverterImpl{
38+
parsers: parsersMap,
39+
}
40+
}

internal/parse/jsonOpenApiParser.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package parse
2+
3+
import (
4+
"errors"
5+
"github.com/rog-golang-buddies/internal/model"
6+
)
7+
8+
//JsonOpenApiParser implementation for parsing json open API files
9+
type JsonOpenApiParser struct {
10+
}
11+
12+
func (joap *JsonOpenApiParser) parse(content []byte) (*model.ApiSpecDoc, error) {
13+
return nil, errors.New("not implemented")
14+
}
15+
16+
func (joap *JsonOpenApiParser) getType() model.AsdFileType {
17+
return model.JsonOpenAPI
18+
}
19+
20+
func NewJsonOpenApiParser() Parser {
21+
return &JsonOpenApiParser{}
22+
}

internal/parse/parser.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package parse
2+
3+
import "github.com/rog-golang-buddies/internal/model"
4+
5+
//Parser is common interface with functionality
6+
//to parse content of the specific API specification document
7+
//and to construct ApiSpecDoc object from it
8+
type Parser interface {
9+
parse(content []byte) (*model.ApiSpecDoc, error)
10+
11+
getType() model.AsdFileType
12+
}

internal/parse/yamlOpenApiParser.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package parse
2+
3+
import (
4+
"errors"
5+
"github.com/rog-golang-buddies/internal/model"
6+
)
7+
8+
//YamlOpenApiParser implementation for parsing yml open API files
9+
type YamlOpenApiParser struct {
10+
}
11+
12+
func (yoap *YamlOpenApiParser) parse(content []byte) (*model.ApiSpecDoc, error) {
13+
return nil, errors.New("not implemented")
14+
}
15+
16+
func (yoap *YamlOpenApiParser) getType() model.AsdFileType {
17+
return model.JsonOpenAPI
18+
}
19+
20+
func NewYamlOpenApiParser() Parser {
21+
return &YamlOpenApiParser{}
22+
}

internal/process/processor.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package process
2+
3+
import (
4+
"context"
5+
"github.com/rog-golang-buddies/internal/load"
6+
"github.com/rog-golang-buddies/internal/model"
7+
"github.com/rog-golang-buddies/internal/parse"
8+
"github.com/rog-golang-buddies/internal/recognize"
9+
)
10+
11+
//UrlProcessor represents provide entrypoint for the url processing
12+
//full processing of the incoming
13+
type UrlProcessor interface {
14+
process(ctx context.Context, url string) (*model.ApiSpecDoc, error)
15+
}
16+
17+
type ProcessorImpl struct {
18+
recognizer recognize.Recognizer
19+
converter parse.Converter
20+
contentLoader load.ContentLoader
21+
}
22+
23+
func (p *ProcessorImpl) process(ctx context.Context, url string) (*model.ApiSpecDoc, error) {
24+
//Check availability of url
25+
//...
26+
27+
//Load content by url
28+
file, err := p.contentLoader.Load(ctx, url)
29+
if err != nil {
30+
return nil, err
31+
}
32+
33+
//If no errs recognize file type by content
34+
fileType, err := p.recognizer.RecognizeFileType(file)
35+
if err != nil {
36+
return nil, err
37+
}
38+
39+
//Parse API spec of defined type
40+
apiSpec, err := p.converter.Convert(file.Content, fileType)
41+
if err != nil {
42+
return nil, err
43+
}
44+
45+
return apiSpec, nil
46+
}
47+
48+
func NewProcessor() (UrlProcessor, error) {
49+
//Need to pass dependencies through constructor
50+
return &ProcessorImpl{
51+
recognizer: recognize.NewRecognizer(),
52+
converter: parse.NewConverter([]parse.Parser{parse.NewYamlOpenApiParser(), parse.NewJsonOpenApiParser()}),
53+
contentLoader: load.NewContentLoader(),
54+
}, nil
55+
}

internal/recognize/recognizer.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package recognize
2+
3+
import (
4+
"errors"
5+
"github.com/rog-golang-buddies/internal/model"
6+
)
7+
8+
//Recognizer provide functionality to recognize file type by content
9+
type Recognizer interface {
10+
//RecognizeFileType recognizes type of the file by content. Probably we may combine it with validation
11+
//Also not sure name is needed here. Better to recognize by content (check is file yaml, if yaml - check version;
12+
//if json - check openApi version) But it is easier to use file extension as starting point to check content.
13+
RecognizeFileType(resource *model.FileResource) (model.AsdFileType, error)
14+
}
15+
16+
type RecognizerImpl struct {
17+
}
18+
19+
func (r *RecognizerImpl) RecognizeFileType(resource *model.FileResource) (model.AsdFileType, error) {
20+
return model.Undefined, errors.New("not implemented")
21+
}
22+
23+
func NewRecognizer() Recognizer {
24+
return &RecognizerImpl{}
25+
}

0 commit comments

Comments
 (0)