@@ -14,9 +14,162 @@ def __init__(self, schema_file_path:str, root_path:str):
1414 def _target_file_without_extension (self ) -> str :
1515 return os .path .join (self .version , "/" .join (self .relative_path_without_extension ))
1616
17+ def _resolve_string_property (self , property ) -> Dict :
18+ string_property_spec = {}
19+ if "_formats" in property and property ["_formats" ]:
20+ if len (property ["_formats" ]) == 1 :
21+ string_property_spec ["format" ] = property ["_formats" ][0 ]
22+ string_property_spec ["type" ] = property ["type" ]
23+ elif len (property ["_formats" ]) > 1 :
24+ string_property_spec ["anyOf" ] = []
25+ for format in property ["_formats" ]:
26+ string_property_spec ["anyOf" ].append ({
27+ "type" : property ["type" ],
28+ "format" : format
29+ })
30+ else :
31+ string_property_spec ["type" ] = property ["type" ]
32+ if "pattern" in property and property ["pattern" ]:
33+ string_property_spec ["pattern" ] = property ["pattern" ]
34+ if "minLength" in property and property ["minLength" ]:
35+ string_property_spec ["minLength" ] = property ["minLength" ]
36+ if "maxLength" in property and property ["maxLength" ]:
37+ string_property_spec ["maxLength" ] = property ["maxLength" ]
38+ return string_property_spec
39+
40+ def _resolve_number_property (self , property ) -> Dict :
41+ number_property_spec = {"type" : property ["type" ]}
42+ if "multipleOf" in property and property ["multipleOf" ]:
43+ number_property_spec ["multipleOf" ] = property ["multipleOf" ]
44+ if "minimum" in property and property ["minimum" ]:
45+ number_property_spec ["minimum" ] = property ["minimum" ]
46+ if "maximum" in property and property ["maximum" ]:
47+ number_property_spec ["maximum" ] = property ["maximum" ]
48+ return number_property_spec
49+
50+ def _resolve_object_property (self , property ):
51+ object_property_spec = {}
52+ if "_embeddedTypes" in property and property ["_embeddedTypes" ]:
53+ if len (property ["_embeddedTypes" ]) == 1 :
54+ object_property_spec ["type" ] = "object"
55+ object_property_spec ["$ref" ] = f"{ property ['_embeddedTypes' ][0 ]} ?format=json-schema"
56+ elif len (property ["_embeddedTypes" ]) > 1 :
57+ object_property_spec ["anyOf" ] = []
58+ for embedded_type in property ["_embeddedTypes" ]:
59+ object_property_spec ["anyOf" ].append ({
60+ "type" : "object" ,
61+ "$ref" : f"{ embedded_type } ?format=json-schema"
62+ })
63+ elif "_linkedTypes" in property and property ["_linkedTypes" ]:
64+ object_property_spec ["type" ] = "object"
65+ object_property_spec ["if" ] = {
66+ "required" : ["@type" ]
67+ }
68+ object_property_spec ["then" ] = {
69+ "properties" : {
70+ "@id" : {
71+ "type" : "string" ,
72+ "format" : "iri"
73+ },
74+ "@type" : {
75+ "type" : "string" ,
76+ "format" : "iri" ,
77+ "enum" : property ["_linkedTypes" ]
78+ }},
79+ "required" : ["@id" ]
80+ }
81+ object_property_spec ["else" ] = {
82+ "properties" : {
83+ "@id" : {
84+ "type" : "string" ,
85+ "format" : "iri"
86+ }
87+ },
88+ "required" : ["@id" ]
89+ }
90+
91+ return object_property_spec
92+
93+ def _resolve_array_property (self , property ):
94+ array_property_spec = {"type" : property ["type" ]}
95+ if "items" in property and property ["items" ]:
96+ if "type" in property ["items" ] and property ["items" ]["type" ]:
97+ if property ["items" ]["type" ] == "string" :
98+ array_property_spec ["items" ] = self ._resolve_string_property (property ["items" ])
99+ elif property ["items" ]["type" ] in ["number" , "float" , "integer" ]:
100+ array_property_spec ["items" ] = self ._resolve_number_property (property ["items" ])
101+ else :
102+ array_property_spec ["items" ] = {"type" : "UNKNOWN_TYPE" }
103+ else :
104+ array_property_spec ["items" ] = self ._resolve_object_property (property )
105+ if "minItems" in property and property ["minItems" ]:
106+ array_property_spec ["minItems" ] = property ["minItems" ]
107+ if "maxItems" in property and property ["maxItems" ]:
108+ array_property_spec ["maxItems" ] = property ["maxItems" ]
109+ if "uniqueItems" in property and property ["uniqueItems" ]:
110+ array_property_spec ["uniqueItems" ] = property ["uniqueItems" ]
111+
112+ return array_property_spec
113+
114+ def _translate_property_specifications (self , property ) -> Dict :
115+ self ._translated_prop_spec = {}
116+
117+ prop_description = property ["description" ] if "description" in property else None
118+ self ._translated_prop_spec ["description" ] = prop_description
119+
120+ self ._translated_prop_spec ["name" ] = property ["name" ]
121+
122+ prop_type = property ["type" ] if "type" in property else "object"
123+
124+ if prop_type == "string" :
125+ self ._translated_prop_spec .update (self ._resolve_string_property (property ))
126+ elif prop_type in ["number" , "float" , "integer" ]:
127+ self ._translated_prop_spec .update (self ._resolve_number_property (property ))
128+ elif prop_type == "object" :
129+ self ._translated_prop_spec .update (self ._resolve_object_property (property ))
130+ elif prop_type == "array" :
131+ self ._translated_prop_spec .update (self ._resolve_array_property (property ))
132+ else :
133+ self ._translated_prop_spec ["type" ] = "UNKNOWN_TYPE"
134+
135+ return self ._translated_prop_spec
136+
137+ def translate (self ):
138+ # set required properties
139+ required_prop = self ._schema_payload ["required" ] if "required" in self ._schema_payload else []
140+ required_prop .extend (["@id" , "@type" ])
141+ # set description
142+ description = self ._schema_payload ['description' ] if "description" in self ._schema_payload else None
143+
144+ self ._translated_schema = {
145+ "$id" : f"{ self ._schema_payload ['_type' ]} ?format=json-schema" ,
146+ "$schema" : "http://json-schema.org/draft-07/schema#" ,
147+ "description" : description ,
148+ "properties" : {
149+ "@id" : {
150+ "description" : "Metadata node identifier." ,
151+ "type" : "string"
152+ },
153+ "@type" : {
154+ "const" : self ._schema_payload ['_type' ],
155+ "description" : "Metadata schema identifier." ,
156+ "type" : "string"
157+ }
158+ },
159+ "required" : sorted (required_prop ),
160+ "title" : self ._schema_payload ['name' ],
161+ "type" : "object"
162+ }
163+
164+ if "properties" in self ._schema_payload and self ._schema_payload ["properties" ]:
165+ for prop_name , prop_spec in self ._schema_payload ["properties" ].items ():
166+ self ._translated_schema ["properties" ][prop_name ] = self ._translate_property_specifications (prop_spec )
167+
17168 def build (self ):
18169 target_file = os .path .join ("target" , "schemas" , f"{ self ._target_file_without_extension ()} .schema.json" )
19170 os .makedirs (os .path .dirname (target_file ), exist_ok = True )
20171
172+ self .translate ()
173+
21174 with open (target_file , "w" ) as target_file :
22- target_file .write (json .dumps (self ._schema_payload , indent = 2 ))
175+ target_file .write (json .dumps (self ._translated_schema , indent = 2 , sort_keys = True ))
0 commit comments