Skip to content

Commit f1315c9

Browse files
authored
Merge pull request #14 from arduino/per1234/generalize-schema-code
Generalize JSON schema handling code
2 parents e3d1875 + fb49bcf commit f1315c9

File tree

4 files changed

+102
-54
lines changed

4 files changed

+102
-54
lines changed

Diff for: check/checkdata/schema/schema.go

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// Package schema contains code for working with JSON schema.
2+
package schema
3+
4+
import (
5+
"net/url"
6+
"path/filepath"
7+
"regexp"
8+
9+
"github.com/arduino/go-paths-helper"
10+
"github.com/xeipuuv/gojsonschema"
11+
)
12+
13+
// Compile compiles the schema files specified by the filename arguments and returns the compiled schema.
14+
func Compile(schemaFilename string, referencedSchemaFilenames []string, schemasPath *paths.Path) *gojsonschema.Schema {
15+
schemaLoader := gojsonschema.NewSchemaLoader()
16+
17+
// Load the referenced schemas.
18+
for _, referencedSchemaFilename := range referencedSchemaFilenames {
19+
referencedSchemaPath := schemasPath.Join(referencedSchemaFilename)
20+
referencedSchemaURI := pathURI(referencedSchemaPath)
21+
err := schemaLoader.AddSchemas(gojsonschema.NewReferenceLoader(referencedSchemaURI))
22+
if err != nil {
23+
panic(err.Error())
24+
}
25+
}
26+
27+
// Compile the schema.
28+
schemaPath := schemasPath.Join(schemaFilename)
29+
schemaURI := pathURI(schemaPath)
30+
compiledSchema, err := schemaLoader.Compile(gojsonschema.NewReferenceLoader(schemaURI))
31+
if err != nil {
32+
panic(err.Error())
33+
}
34+
return compiledSchema
35+
}
36+
37+
// Validate validates an instance against a JSON schema and returns the gojsonschema.Result object.
38+
func Validate(instanceObject interface{}, schemaObject *gojsonschema.Schema) *gojsonschema.Result {
39+
result, err := schemaObject.Validate(gojsonschema.NewGoLoader(instanceObject))
40+
if err != nil {
41+
panic(err.Error())
42+
}
43+
44+
return result
45+
}
46+
47+
// RequiredPropertyMissing returns whether the given required property is missing from the document.
48+
func RequiredPropertyMissing(propertyName string, validationResult *gojsonschema.Result) bool {
49+
return ValidationErrorMatch("required", "(root)", propertyName+" is required", validationResult)
50+
}
51+
52+
// PropertyPatternMismatch returns whether the given property did not match the regular expression defined in the JSON schema.
53+
func PropertyPatternMismatch(propertyName string, validationResult *gojsonschema.Result) bool {
54+
return ValidationErrorMatch("pattern", propertyName, "", validationResult)
55+
}
56+
57+
// ValidationErrorMatch returns whether the given query matches against the JSON schema validation error.
58+
// See: https://github.com/xeipuuv/gojsonschema#working-with-errors
59+
func ValidationErrorMatch(typeQuery string, fieldQuery string, descriptionQueryRegexp string, validationResult *gojsonschema.Result) bool {
60+
if validationResult.Valid() {
61+
// No error, so nothing to match
62+
return false
63+
}
64+
for _, validationError := range validationResult.Errors() {
65+
if typeQuery == "" || typeQuery == validationError.Type() {
66+
if fieldQuery == "" || fieldQuery == validationError.Field() {
67+
descriptionQuery := regexp.MustCompile(descriptionQueryRegexp)
68+
return descriptionQuery.MatchString(validationError.Description())
69+
}
70+
}
71+
}
72+
73+
return false
74+
}
75+
76+
// pathURI returns the URI representation of the path argument.
77+
func pathURI(path *paths.Path) string {
78+
uriFriendlyPath := filepath.ToSlash(path.String())
79+
pathURI := url.URL{
80+
Scheme: "file",
81+
Path: uriFriendlyPath,
82+
}
83+
84+
return pathURI.String()
85+
}

Diff for: check/checkfunctions/library.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ package checkfunctions
44

55
import (
66
"github.com/arduino/arduino-check/check/checkdata"
7+
"github.com/arduino/arduino-check/check/checkdata/schema"
78
"github.com/arduino/arduino-check/check/checkresult"
8-
"github.com/arduino/arduino-check/project/library/libraryproperties"
99
)
1010

1111
// LibraryPropertiesFormat checks for invalid library.properties format.
@@ -22,7 +22,7 @@ func LibraryPropertiesNameFieldMissing() (result checkresult.Type, output string
2222
return checkresult.NotRun, ""
2323
}
2424

25-
if libraryproperties.FieldMissing("name", checkdata.LibraryPropertiesSchemaValidationResult()) {
25+
if schema.RequiredPropertyMissing("name", checkdata.LibraryPropertiesSchemaValidationResult()) {
2626
return checkresult.Fail, ""
2727
}
2828
return checkresult.Pass, ""
@@ -34,7 +34,7 @@ func LibraryPropertiesNameFieldDisallowedCharacters() (result checkresult.Type,
3434
return checkresult.NotRun, ""
3535
}
3636

37-
if libraryproperties.FieldPatternMismatch("name", checkdata.LibraryPropertiesSchemaValidationResult()) {
37+
if schema.PropertyPatternMismatch("name", checkdata.LibraryPropertiesSchemaValidationResult()) {
3838
return checkresult.Fail, ""
3939
}
4040

@@ -47,7 +47,7 @@ func LibraryPropertiesVersionFieldMissing() (result checkresult.Type, output str
4747
return checkresult.NotRun, ""
4848
}
4949

50-
if libraryproperties.FieldMissing("version", checkdata.LibraryPropertiesSchemaValidationResult()) {
50+
if schema.RequiredPropertyMissing("version", checkdata.LibraryPropertiesSchemaValidationResult()) {
5151
return checkresult.Fail, ""
5252
}
5353
return checkresult.Pass, ""

Diff for: configuration/configuration.go

+8
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
package configuration
33

44
import (
5+
"os"
6+
57
"github.com/arduino/arduino-check/configuration/checkmode"
68
"github.com/arduino/arduino-check/project/projecttype"
79
"github.com/arduino/arduino-check/result/outputformat"
@@ -79,3 +81,9 @@ var targetPath *paths.Path
7981
func TargetPath() *paths.Path {
8082
return targetPath
8183
}
84+
85+
// SchemasPath returns the path to the folder containing the JSON schemas.
86+
func SchemasPath() *paths.Path {
87+
workingPath, _ := os.Getwd()
88+
return paths.New(workingPath)
89+
}

Diff for: project/library/libraryproperties/libraryproperties.go

+5-50
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@
22
package libraryproperties
33

44
import (
5-
"net/url"
6-
"os"
7-
"path/filepath"
8-
5+
"github.com/arduino/arduino-check/check/checkdata/schema"
6+
"github.com/arduino/arduino-check/configuration"
97
"github.com/arduino/go-paths-helper"
108
"github.com/arduino/go-properties-orderedmap"
119
"github.com/xeipuuv/gojsonschema"
@@ -22,51 +20,8 @@ func Properties(libraryPath *paths.Path) (*properties.Map, error) {
2220

2321
// Validate validates library.properties data against the JSON schema.
2422
func Validate(libraryProperties *properties.Map) *gojsonschema.Result {
25-
workingPath, _ := os.Getwd()
26-
schemaPath := paths.New(workingPath).Join("arduino-library-properties-schema.json")
27-
uriFriendlySchemaPath := filepath.ToSlash(schemaPath.String())
28-
schemaPathURI := url.URL{
29-
Scheme: "file",
30-
Path: uriFriendlySchemaPath,
31-
}
32-
schemaLoader := gojsonschema.NewReferenceLoader(schemaPathURI.String())
33-
34-
documentLoader := gojsonschema.NewGoLoader(libraryProperties)
35-
36-
result, err := gojsonschema.Validate(schemaLoader, documentLoader)
37-
if err != nil {
38-
panic(err.Error())
39-
}
40-
41-
return result
42-
}
43-
44-
// FieldMissing returns whether the given required field is missing from library.properties.
45-
func FieldMissing(fieldName string, validationResult *gojsonschema.Result) bool {
46-
return ValidationErrorMatch("required", "(root)", fieldName+" is required", validationResult)
47-
}
48-
49-
// FieldPatternMismatch returns whether the given field did not match the regular expression defined in the JSON schema.
50-
func FieldPatternMismatch(fieldName string, validationResult *gojsonschema.Result) bool {
51-
return ValidationErrorMatch("pattern", fieldName, "", validationResult)
52-
}
53-
54-
// ValidationErrorMatch returns whether the given query matches against the JSON schema validation error.
55-
// See: https://github.com/xeipuuv/gojsonschema#working-with-errors
56-
func ValidationErrorMatch(typeQuery string, fieldQuery string, descriptionQuery string, validationResult *gojsonschema.Result) bool {
57-
if validationResult.Valid() {
58-
// No error, so nothing to match
59-
return false
60-
}
61-
for _, validationError := range validationResult.Errors() {
62-
if typeQuery == "" || typeQuery == validationError.Type() {
63-
if fieldQuery == "" || fieldQuery == validationError.Field() {
64-
if descriptionQuery == "" || descriptionQuery == validationError.Description() {
65-
return true
66-
}
67-
}
68-
}
69-
}
23+
referencedSchemaFilenames := []string{}
24+
schemaObject := schema.Compile("arduino-library-properties-schema.json", referencedSchemaFilenames, configuration.SchemasPath())
7025

71-
return false
26+
return schema.Validate(libraryProperties, schemaObject)
7227
}

0 commit comments

Comments
 (0)