openphar 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. checksums.yaml +7 -0
  2. data/README.adoc +221 -0
  3. data/lib/openphar/cli/main.rb +137 -0
  4. data/lib/openphar/cli.rb +11 -0
  5. data/lib/openphar/core/slug_generator.rb +107 -0
  6. data/lib/openphar/core.rb +11 -0
  7. data/lib/openphar/errors/configuration_error.rb +8 -0
  8. data/lib/openphar/errors/monograph_not_found_error.rb +15 -0
  9. data/lib/openphar/errors/parse_error.rb +18 -0
  10. data/lib/openphar/errors/unknown_format_error.rb +8 -0
  11. data/lib/openphar/errors/unknown_publisher_error.rb +8 -0
  12. data/lib/openphar/errors/unknown_type_error.rb +8 -0
  13. data/lib/openphar/errors/validation_error.rb +15 -0
  14. data/lib/openphar/errors.rb +17 -0
  15. data/lib/openphar/exporters/coverage_validator.rb +265 -0
  16. data/lib/openphar/exporters/neo4j/model_registry.rb +130 -0
  17. data/lib/openphar/exporters/neo4j/node_builder.rb +84 -0
  18. data/lib/openphar/exporters/neo4j/property_mapper.rb +154 -0
  19. data/lib/openphar/exporters/neo4j/relationship_builder.rb +87 -0
  20. data/lib/openphar/exporters/neo4j.rb +16 -0
  21. data/lib/openphar/exporters/neo4j_exporter.rb +199 -0
  22. data/lib/openphar/exporters.rb +15 -0
  23. data/lib/openphar/linkers/chp/cross_edition_linker.rb +101 -0
  24. data/lib/openphar/linkers/chp.rb +11 -0
  25. data/lib/openphar/linkers/cross_publisher_linker.rb +295 -0
  26. data/lib/openphar/linkers/herbapedia_linker.rb +125 -0
  27. data/lib/openphar/linkers.rb +13 -0
  28. data/lib/openphar/migrators/chp/classifier.rb +86 -0
  29. data/lib/openphar/migrators/chp.rb +15 -0
  30. data/lib/openphar/migrators/chp_migrator.rb +130 -0
  31. data/lib/openphar/migrators/jp_migrator.rb +345 -0
  32. data/lib/openphar/migrators/phint_migrator.rb +426 -0
  33. data/lib/openphar/migrators.rb +15 -0
  34. data/lib/openphar/models/ahp.rb +25 -0
  35. data/lib/openphar/models/amino_acid_monograph.rb +28 -0
  36. data/lib/openphar/models/api.rb +29 -0
  37. data/lib/openphar/models/assay_specification.rb +19 -0
  38. data/lib/openphar/models/base_entity.rb +221 -0
  39. data/lib/openphar/models/biological_substance_monograph.rb +31 -0
  40. data/lib/openphar/models/chemical_drug_monograph.rb +39 -0
  41. data/lib/openphar/models/chp/biologic.rb +28 -0
  42. data/lib/openphar/models/chp/chemical_preparation.rb +28 -0
  43. data/lib/openphar/models/chp/chemical_substance.rb +28 -0
  44. data/lib/openphar/models/chp/general_chapter.rb +30 -0
  45. data/lib/openphar/models/chp/monograph.rb +116 -0
  46. data/lib/openphar/models/chp/section.rb +37 -0
  47. data/lib/openphar/models/chp/tcm_crude_drug.rb +28 -0
  48. data/lib/openphar/models/chp/tcm_extract.rb +29 -0
  49. data/lib/openphar/models/chp/tcm_formulation.rb +28 -0
  50. data/lib/openphar/models/chp.rb +33 -0
  51. data/lib/openphar/models/crude_drug_monograph.rb +31 -0
  52. data/lib/openphar/models/edition.rb +41 -0
  53. data/lib/openphar/models/formulation_monograph.rb +31 -0
  54. data/lib/openphar/models/hkcmms.rb +26 -0
  55. data/lib/openphar/models/identification_specification.rb +19 -0
  56. data/lib/openphar/models/jp/kampo_formula.rb +94 -0
  57. data/lib/openphar/models/jp.rb +21 -0
  58. data/lib/openphar/models/limit.rb +54 -0
  59. data/lib/openphar/models/mineral_substance_monograph.rb +28 -0
  60. data/lib/openphar/models/monograph.rb +58 -0
  61. data/lib/openphar/models/ph_int/buffer_solution.rb +38 -0
  62. data/lib/openphar/models/ph_int/dosage_form_monograph.rb +43 -0
  63. data/lib/openphar/models/ph_int/radiopharmaceutical_monograph.rb +52 -0
  64. data/lib/openphar/models/ph_int/reagent.rb +50 -0
  65. data/lib/openphar/models/ph_int/reference_substance.rb +50 -0
  66. data/lib/openphar/models/ph_int/test_method.rb +50 -0
  67. data/lib/openphar/models/ph_int/test_solution.rb +39 -0
  68. data/lib/openphar/models/ph_int/volumetric_solution.rb +38 -0
  69. data/lib/openphar/models/ph_int.rb +37 -0
  70. data/lib/openphar/models/physical_specification.rb +17 -0
  71. data/lib/openphar/models/publisher.rb +98 -0
  72. data/lib/openphar/models/purity_specification.rb +16 -0
  73. data/lib/openphar/models/supplement.rb +31 -0
  74. data/lib/openphar/models/test_specification.rb +29 -0
  75. data/lib/openphar/models/thp.rb +24 -0
  76. data/lib/openphar/models/vitamin_monograph.rb +28 -0
  77. data/lib/openphar/models.rb +58 -0
  78. data/lib/openphar/monograph_merger.rb +374 -0
  79. data/lib/openphar/parsers/base_monograph_parser.rb +108 -0
  80. data/lib/openphar/parsers/jp_html_parser.rb +92 -0
  81. data/lib/openphar/parsers/jp_html_parser_base.rb +113 -0
  82. data/lib/openphar/parsers/jp_ja_html_parser.rb +220 -0
  83. data/lib/openphar/parsers/phint_json_parser.rb +332 -0
  84. data/lib/openphar/parsers.rb +21 -0
  85. data/lib/openphar/registry/publisher_registry.rb +46 -0
  86. data/lib/openphar/registry/type_registry.rb +147 -0
  87. data/lib/openphar/registry.rb +24 -0
  88. data/lib/openphar/repositories/monograph_repository.rb +350 -0
  89. data/lib/openphar/repositories.rb +11 -0
  90. data/lib/openphar/transformers/jsonld_transformer.rb +106 -0
  91. data/lib/openphar/transformers.rb +11 -0
  92. data/lib/openphar/version.rb +5 -0
  93. data/lib/openphar.rb +119 -0
  94. data/ontology/bibliographic/edition.ttl +267 -0
  95. data/ontology/context/chp.jsonld +69 -0
  96. data/ontology/context/crude-drugs.jsonld +56 -0
  97. data/ontology/context/pharmacopoeia.jsonld +631 -0
  98. data/ontology/core/identification.ttl +456 -0
  99. data/ontology/core/pharmacopoeia.ttl +3427 -0
  100. data/ontology/core/substance-form.ttl +302 -0
  101. data/ontology/core/unit.ttl +493 -0
  102. data/ontology/publisher/chp/extensions.ttl +186 -0
  103. data/ontology/publisher/phint/extensions.ttl +327 -0
  104. data/ontology/quality/test-method.ttl +610 -0
  105. data/shapes/chp/monograph.ttl +153 -0
  106. data/shapes/edition-shapes.ttl +230 -0
  107. data/shapes/monograph-shapes.ttl +1324 -0
  108. metadata +319 -0
@@ -0,0 +1,1324 @@
1
+ # Open Pharmacopoeia - SHACL Shapes for Monograph Validation
2
+ #
3
+ # This file defines SHACL shapes for validating pharmacopoeia monograph data.
4
+ # Ensures that all required properties are present and have correct types.
5
+
6
+ @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
7
+ @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
8
+ @prefix owl: <http://www.w3.org/2002/07/owl#> .
9
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
10
+ @prefix skos: <http://www.w3.org/2004/02/skos/core#> .
11
+ @prefix sh: <http://www.w3.org/ns/shacl#> .
12
+ @prefix op: <https://www.openphar.org/ontology/core/> .
13
+ @prefix shape: <https://www.openphar.org/shapes/> .
14
+
15
+ <https://www.openphar.org/shapes/monograph-shapes>
16
+ a owl:Ontology ;
17
+ rdfs:label "Open Pharmacopoeia Monograph Shapes"@en ;
18
+ rdfs:comment "SHACL shapes for validating pharmacopoeia monographs."@en ;
19
+ owl:imports <https://www.openphar.org/ontology/core> ;
20
+ sh:declare [
21
+ sh:prefix "op" ;
22
+ sh:namespace "https://www.openphar.org/ontology/core/"^^xsd:anyURI
23
+ ] , [
24
+ sh:prefix "skos" ;
25
+ sh:namespace "http://www.w3.org/2004/02/skos/core#"^^xsd:anyURI
26
+ ] .
27
+
28
+ # =============================================================================
29
+ # PHARMACOPOEIA MONOGRAPH SHAPE
30
+ # =============================================================================
31
+
32
+ shape:PharmacopoeiaMonographShape
33
+ a sh:NodeShape ;
34
+ sh:targetClass op:PharmacopoeiaMonograph ;
35
+
36
+ # Required properties
37
+ sh:property [
38
+ sh:path op:publisher ;
39
+ sh:class op:Publisher ;
40
+ sh:minCount 1 ;
41
+ sh:maxCount 1 ;
42
+ sh:message "A monograph must have exactly one publisher."@en
43
+ ] ;
44
+
45
+ sh:property [
46
+ sh:path op:monographId ;
47
+ sh:datatype xsd:string ;
48
+ sh:minCount 1 ;
49
+ sh:maxCount 1 ;
50
+ sh:message "A monograph must have exactly one monograph ID."@en
51
+ ] ;
52
+
53
+ sh:property [
54
+ sh:path skos:prefLabel ;
55
+ sh:datatype rdf:langString ;
56
+ sh:minCount 1 ;
57
+ sh:message "A monograph must have at least one preferred label."@en
58
+ ] ;
59
+
60
+ # Optional but recommended properties
61
+ sh:property [
62
+ sh:path op:status ;
63
+ sh:class op:MonographStatus ;
64
+ sh:maxCount 1 ;
65
+ sh:severity sh:Warning ;
66
+ sh:message "A monograph should have a status."@en
67
+ ] ;
68
+
69
+ sh:property [
70
+ sh:path op:effectiveDate ;
71
+ sh:datatype xsd:date ;
72
+ sh:maxCount 1 ;
73
+ sh:severity sh:Info ;
74
+ sh:message "A monograph may have an effective date."@en
75
+ ] ;
76
+
77
+ sh:property [
78
+ sh:path op:version ;
79
+ sh:datatype xsd:string ;
80
+ sh:maxCount 1 ;
81
+ sh:severity sh:Info ;
82
+ sh:message "A monograph may have a version."@en
83
+ ] ;
84
+
85
+ # External references
86
+ sh:property [
87
+ sh:path op:referencesPreparation ;
88
+ sh:nodeKind sh:IRI ;
89
+ sh:maxCount 1 ;
90
+ sh:severity sh:Warning ;
91
+ sh:message "A monograph should reference a HerbalPreparation in data-herbapedia."@en
92
+ ] ;
93
+
94
+ sh:property [
95
+ sh:path op:referencesTCMProfile ;
96
+ sh:nodeKind sh:IRI ;
97
+ sh:maxCount 1 ;
98
+ sh:severity sh:Info ;
99
+ sh:message "A monograph may reference a TCMProfile in data-herbapedia."@en
100
+ ] ;
101
+
102
+ sh:property [
103
+ sh:path op:referencesAyurvedaProfile ;
104
+ sh:nodeKind sh:IRI ;
105
+ sh:maxCount 1 ;
106
+ sh:severity sh:Info ;
107
+ sh:message "A monograph may reference an AyurvedaProfile in data-herbapedia."@en
108
+ ] ;
109
+
110
+ sh:property [
111
+ sh:path op:referencesWesternProfile ;
112
+ sh:nodeKind sh:IRI ;
113
+ sh:maxCount 1 ;
114
+ sh:severity sh:Info ;
115
+ sh:message "A monograph may reference a WesternProfile in data-herbapedia."@en
116
+ ] ;
117
+
118
+ # Definition
119
+ sh:property [
120
+ sh:path op:definition ;
121
+ sh:datatype rdf:langString ;
122
+ sh:maxCount 1 ;
123
+ sh:severity sh:Warning ;
124
+ sh:message "A monograph should have a definition."@en
125
+ ] ;
126
+
127
+ # Test specifications
128
+ sh:property [
129
+ sh:path op:testSpecification ;
130
+ sh:class op:TestSpecification ;
131
+ sh:node shape:TestSpecificationShape ;
132
+ sh:severity sh:Info ;
133
+ sh:message "A monograph may have test specifications."@en
134
+ ] ;
135
+
136
+ # Storage
137
+ sh:property [
138
+ sh:path op:storageContainer ;
139
+ sh:datatype rdf:langString ;
140
+ sh:maxCount 1 ;
141
+ sh:severity sh:Info ;
142
+ sh:message "A monograph may specify storage container requirements."@en
143
+ ] ;
144
+
145
+ sh:property [
146
+ sh:path op:storageConditions ;
147
+ sh:datatype rdf:langString ;
148
+ sh:maxCount 1 ;
149
+ sh:severity sh:Info ;
150
+ sh:message "A monograph may specify storage conditions."@en
151
+ ] .
152
+
153
+ # =============================================================================
154
+ # CRUDE DRUG MONOGRAPH SHAPE
155
+ # =============================================================================
156
+
157
+ shape:CrudeDrugMonographShape
158
+ a sh:NodeShape ;
159
+ sh:targetClass op:CrudeDrugMonograph ;
160
+
161
+ # Inherits all constraints from PharmacopoeiaMonograph
162
+ sh:and ( shape:PharmacopoeiaMonographShape ) ;
163
+
164
+ # Additional required properties for crude drugs
165
+ sh:property [
166
+ sh:path op:botanicalSource ;
167
+ sh:class op:BotanicalSource ;
168
+ sh:minCount 1 ;
169
+ sh:node shape:BotanicalSourceShape ;
170
+ sh:message "A crude drug monograph must have at least one botanical source."@en
171
+ ] ;
172
+
173
+ sh:property [
174
+ sh:path op:macroscopicDescription ;
175
+ sh:class op:MacroscopicDescription ;
176
+ sh:node shape:MacroscopicDescriptionShape ;
177
+ sh:severity sh:Warning ;
178
+ sh:message "A crude drug monograph should have a macroscopic description."@en
179
+ ] ;
180
+
181
+ sh:property [
182
+ sh:path op:microscopicDescription ;
183
+ sh:class op:MicroscopicDescription ;
184
+ sh:node shape:MicroscopicDescriptionShape ;
185
+ sh:severity sh:Warning ;
186
+ sh:message "A crude drug monograph should have a microscopic description."@en
187
+ ] .
188
+
189
+ # =============================================================================
190
+ # TEST SPECIFICATION SHAPE
191
+ # =============================================================================
192
+
193
+ shape:TestSpecificationShape
194
+ a sh:NodeShape ;
195
+ sh:targetClass op:TestSpecification ;
196
+
197
+ sh:property [
198
+ sh:path op:testName ;
199
+ sh:datatype rdf:langString ;
200
+ sh:minCount 1 ;
201
+ sh:maxCount 1 ;
202
+ sh:message "A test specification must have exactly one test name."@en
203
+ ] ;
204
+
205
+ sh:property [
206
+ sh:path op:testType ;
207
+ sh:class op:TestType ;
208
+ sh:minCount 1 ;
209
+ sh:maxCount 1 ;
210
+ sh:message "A test specification must have exactly one test type."@en
211
+ ] ;
212
+
213
+ sh:property [
214
+ sh:path op:harmonizedMethod ;
215
+ sh:class op:HarmonizedMethod ;
216
+ sh:maxCount 1 ;
217
+ sh:severity sh:Info ;
218
+ sh:message "A test specification may reference a harmonized method."@en
219
+ ] ;
220
+
221
+ sh:property [
222
+ sh:path op:publisherMethod ;
223
+ sh:class op:PublisherMethod ;
224
+ sh:maxCount 1 ;
225
+ sh:severity sh:Info ;
226
+ sh:message "A test specification may reference a publisher method."@en
227
+ ] ;
228
+
229
+ sh:property [
230
+ sh:path op:limit ;
231
+ sh:class op:Limit ;
232
+ sh:node shape:LimitShape ;
233
+ sh:maxCount 1 ;
234
+ sh:severity sh:Info ;
235
+ sh:message "A test specification may have a limit."@en
236
+ ] .
237
+
238
+ # =============================================================================
239
+ # ASSAY SPECIFICATION SHAPE
240
+ # =============================================================================
241
+
242
+ shape:AssaySpecificationShape
243
+ a sh:NodeShape ;
244
+ sh:targetClass op:AssaySpecification ;
245
+
246
+ sh:and ( shape:TestSpecificationShape ) ;
247
+
248
+ sh:property [
249
+ sh:path op:assayTarget ;
250
+ sh:datatype rdf:langString ;
251
+ sh:minCount 1 ;
252
+ sh:maxCount 1 ;
253
+ sh:message "An assay specification must specify the assay target."@en
254
+ ] ;
255
+
256
+ sh:property [
257
+ sh:path op:limit ;
258
+ sh:class op:Limit ;
259
+ sh:minCount 1 ;
260
+ sh:node shape:LimitShape ;
261
+ sh:message "An assay specification must have a limit."@en
262
+ ] .
263
+
264
+ # =============================================================================
265
+ # LIMIT SHAPE
266
+ # =============================================================================
267
+
268
+ shape:LimitShape
269
+ a sh:NodeShape ;
270
+ sh:targetClass op:Limit ;
271
+
272
+ sh:property [
273
+ sh:path op:limitType ;
274
+ sh:class op:LimitType ;
275
+ sh:minCount 1 ;
276
+ sh:maxCount 1 ;
277
+ sh:message "A limit must have exactly one limit type."@en
278
+ ] ;
279
+
280
+ sh:property [
281
+ sh:path op:limitUnit ;
282
+ sh:class op:Unit ;
283
+ sh:minCount 1 ;
284
+ sh:maxCount 1 ;
285
+ sh:message "A limit must have exactly one unit."@en
286
+ ] ;
287
+
288
+ # For simple limits (min, max, exact)
289
+ sh:property [
290
+ sh:path op:limitValue ;
291
+ sh:datatype xsd:decimal ;
292
+ sh:maxCount 1 ;
293
+ sh:message "A limit may have a single limit value."@en
294
+ ] ;
295
+
296
+ # For range limits
297
+ sh:property [
298
+ sh:path op:lowerLimit ;
299
+ sh:datatype xsd:decimal ;
300
+ sh:maxCount 1 ;
301
+ sh:message "A limit may have a lower bound."@en
302
+ ] ;
303
+
304
+ sh:property [
305
+ sh:path op:upperLimit ;
306
+ sh:datatype xsd:decimal ;
307
+ sh:maxCount 1 ;
308
+ sh:message "A limit may have an upper bound."@en
309
+ ] .
310
+
311
+ # =============================================================================
312
+ # BOTANICAL SOURCE SHAPE
313
+ # =============================================================================
314
+
315
+ shape:BotanicalSourceShape
316
+ a sh:NodeShape ;
317
+ sh:targetClass op:BotanicalSource ;
318
+
319
+ sh:property [
320
+ sh:path op:referencesPlantSpecies ;
321
+ sh:nodeKind sh:IRI ;
322
+ sh:minCount 1 ;
323
+ sh:message "A botanical source must reference a PlantSpecies in data-herbapedia."@en
324
+ ] ;
325
+
326
+ sh:property [
327
+ sh:path op:plantPartUsed ;
328
+ sh:datatype rdf:langString ;
329
+ sh:minCount 1 ;
330
+ sh:maxCount 1 ;
331
+ sh:message "A botanical source must specify the plant part used."@en
332
+ ] ;
333
+
334
+ sh:property [
335
+ sh:path op:collectionPeriod ;
336
+ sh:datatype rdf:langString ;
337
+ sh:maxCount 1 ;
338
+ sh:severity sh:Info ;
339
+ sh:message "A botanical source may specify the collection period."@en
340
+ ] .
341
+
342
+ # =============================================================================
343
+ # MACROSCOPIC DESCRIPTION SHAPE
344
+ # =============================================================================
345
+
346
+ shape:MacroscopicDescriptionShape
347
+ a sh:NodeShape ;
348
+ sh:targetClass op:MacroscopicDescription ;
349
+
350
+ sh:property [
351
+ sh:path op:color ;
352
+ sh:datatype rdf:langString ;
353
+ sh:maxCount 1 ;
354
+ sh:severity sh:Warning ;
355
+ sh:message "A macroscopic description should specify the color."@en
356
+ ] ;
357
+
358
+ sh:property [
359
+ sh:path op:shape ;
360
+ sh:datatype rdf:langString ;
361
+ sh:maxCount 1 ;
362
+ sh:severity sh:Warning ;
363
+ sh:message "A macroscopic description should specify the shape."@en
364
+ ] ;
365
+
366
+ sh:property [
367
+ sh:path op:size ;
368
+ sh:datatype rdf:langString ;
369
+ sh:maxCount 1 ;
370
+ sh:severity sh:Info ;
371
+ sh:message "A macroscopic description may specify the size."@en
372
+ ] ;
373
+
374
+ sh:property [
375
+ sh:path op:texture ;
376
+ sh:datatype rdf:langString ;
377
+ sh:maxCount 1 ;
378
+ sh:severity sh:Info ;
379
+ sh:message "A macroscopic description may specify the texture."@en
380
+ ] ;
381
+
382
+ sh:property [
383
+ sh:path op:odor ;
384
+ sh:datatype rdf:langString ;
385
+ sh:maxCount 1 ;
386
+ sh:severity sh:Info ;
387
+ sh:message "A macroscopic description may specify the odor."@en
388
+ ] ;
389
+
390
+ sh:property [
391
+ sh:path op:taste ;
392
+ sh:datatype rdf:langString ;
393
+ sh:maxCount 1 ;
394
+ sh:severity sh:Info ;
395
+ sh:message "A macroscopic description may specify the taste."@en
396
+ ] ;
397
+
398
+ sh:property [
399
+ sh:path op:fracture ;
400
+ sh:datatype rdf:langString ;
401
+ sh:maxCount 1 ;
402
+ sh:severity sh:Info ;
403
+ sh:message "A macroscopic description may specify the fracture."@en
404
+ ] .
405
+
406
+ # =============================================================================
407
+ # MICROSCOPIC DESCRIPTION SHAPE
408
+ # =============================================================================
409
+
410
+ shape:MicroscopicDescriptionShape
411
+ a sh:NodeShape ;
412
+ sh:targetClass op:MicroscopicDescription ;
413
+
414
+ sh:property [
415
+ sh:path op:transverseSection ;
416
+ sh:datatype rdf:langString ;
417
+ sh:maxCount 1 ;
418
+ sh:severity sh:Info ;
419
+ sh:message "A microscopic description may specify transverse section features."@en
420
+ ] ;
421
+
422
+ sh:property [
423
+ sh:path op:powderCharacteristics ;
424
+ sh:datatype rdf:langString ;
425
+ sh:maxCount 1 ;
426
+ sh:severity sh:Info ;
427
+ sh:message "A microscopic description may specify powder characteristics."@en
428
+ ] ;
429
+
430
+ sh:property [
431
+ sh:path op:diagnosticFeatures ;
432
+ sh:datatype rdf:langString ;
433
+ sh:severity sh:Info ;
434
+ sh:message "A microscopic description may specify diagnostic features."@en
435
+ ] .
436
+
437
+ # =============================================================================
438
+ # PUBLISHER METHOD SHAPE
439
+ # =============================================================================
440
+
441
+ shape:PublisherMethodShape
442
+ a sh:NodeShape ;
443
+ sh:targetClass op:PublisherMethod ;
444
+
445
+ sh:property [
446
+ sh:path skos:prefLabel ;
447
+ sh:datatype rdf:langString ;
448
+ sh:minCount 1 ;
449
+ sh:maxCount 1 ;
450
+ sh:message "A publisher method must have a preferred label."@en
451
+ ] ;
452
+
453
+ sh:property [
454
+ sh:path op:methodPublisher ;
455
+ sh:class op:Publisher ;
456
+ sh:minCount 1 ;
457
+ sh:maxCount 1 ;
458
+ sh:message "A publisher method must specify its publisher."@en
459
+ ] ;
460
+
461
+ sh:property [
462
+ sh:path op:equivalentTo ;
463
+ sh:class op:HarmonizedMethod ;
464
+ sh:severity sh:Info ;
465
+ sh:message "A publisher method may be equivalent to a harmonized method."@en
466
+ ] .
467
+
468
+ # =============================================================================
469
+ # CHEMICAL DRUG MONOGRAPH SHAPE
470
+ # =============================================================================
471
+
472
+ shape:ChemicalDrugMonographShape
473
+ a sh:NodeShape ;
474
+ sh:targetClass op:ChemicalDrugMonograph ;
475
+
476
+ # Inherits all constraints from PharmacopoeiaMonograph
477
+ sh:and ( shape:PharmacopoeiaMonographShape ) ;
478
+
479
+ # Required chemical identification properties
480
+ sh:property [
481
+ sh:path op:molecularFormula ;
482
+ sh:datatype xsd:string ;
483
+ sh:minCount 1 ;
484
+ sh:maxCount 1 ;
485
+ sh:message "A chemical drug monograph must have exactly one molecular formula."@en
486
+ ] ;
487
+
488
+ sh:property [
489
+ sh:path op:molecularWeight ;
490
+ sh:datatype xsd:decimal ;
491
+ sh:minCount 1 ;
492
+ sh:maxCount 1 ;
493
+ sh:message "A chemical drug monograph must have exactly one molecular weight."@en
494
+ ] ;
495
+
496
+ sh:property [
497
+ sh:path op:casNumber ;
498
+ sh:datatype xsd:string ;
499
+ sh:minCount 1 ;
500
+ sh:maxCount 1 ;
501
+ sh:message "A chemical drug monograph must have exactly one CAS Registry Number."@en
502
+ ] ;
503
+
504
+ # Optional but recommended chemical properties
505
+ sh:property [
506
+ sh:path op:systematicName ;
507
+ sh:datatype rdf:langString ;
508
+ sh:maxCount 1 ;
509
+ sh:severity sh:Warning ;
510
+ sh:message "A chemical drug monograph should have a systematic (IUPAC) name."@en
511
+ ] ;
512
+
513
+ sh:property [
514
+ sh:path op:chemicalStructure ;
515
+ sh:datatype xsd:anyURI ;
516
+ sh:maxCount 1 ;
517
+ sh:severity sh:Info ;
518
+ sh:message "A chemical drug monograph may reference a chemical structure (InChI, SMILES, etc.)."@en
519
+ ] ;
520
+
521
+ sh:property [
522
+ sh:path op:inchi ;
523
+ sh:datatype xsd:string ;
524
+ sh:maxCount 1 ;
525
+ sh:severity sh:Info ;
526
+ sh:message "A chemical drug monograph may have an InChI identifier."@en
527
+ ] ;
528
+
529
+ sh:property [
530
+ sh:path op:inchiKey ;
531
+ sh:datatype xsd:string ;
532
+ sh:maxCount 1 ;
533
+ sh:severity sh:Info ;
534
+ sh:message "A chemical drug monograph may have an InChIKey."@en
535
+ ] ;
536
+
537
+ sh:property [
538
+ sh:path op:smiles ;
539
+ sh:datatype xsd:string ;
540
+ sh:maxCount 1 ;
541
+ sh:severity sh:Info ;
542
+ sh:message "A chemical drug monograph may have a SMILES notation."@en
543
+ ] .
544
+
545
+ # =============================================================================
546
+ # VITAMIN MONOGRAPH SHAPE
547
+ # =============================================================================
548
+
549
+ shape:VitaminMonographShape
550
+ a sh:NodeShape ;
551
+ sh:targetClass op:VitaminMonograph ;
552
+
553
+ # Inherits all constraints from ChemicalDrugMonograph
554
+ sh:and ( shape:ChemicalDrugMonographShape ) ;
555
+
556
+ # Vitamin-specific properties
557
+ sh:property [
558
+ sh:path op:vitaminType ;
559
+ sh:class op:VitaminType ;
560
+ sh:minCount 1 ;
561
+ sh:maxCount 1 ;
562
+ sh:message "A vitamin monograph must specify its vitamin type (e.g., Vitamin C, Vitamin D)."@en
563
+ ] ;
564
+
565
+ sh:property [
566
+ sh:path op:biologicalActivity ;
567
+ sh:datatype rdf:langString ;
568
+ sh:maxCount 1 ;
569
+ sh:severity sh:Info ;
570
+ sh:message "A vitamin monograph may specify biological activity in IU."@en
571
+ ] .
572
+
573
+ # =============================================================================
574
+ # AMINO ACID MONOGRAPH SHAPE
575
+ # =============================================================================
576
+
577
+ shape:AminoAcidMonographShape
578
+ a sh:NodeShape ;
579
+ sh:targetClass op:AminoAcidMonograph ;
580
+
581
+ # Inherits all constraints from ChemicalDrugMonograph
582
+ sh:and ( shape:ChemicalDrugMonographShape ) ;
583
+
584
+ # Amino acid-specific properties
585
+ sh:property [
586
+ sh:path op:aminoAcidType ;
587
+ sh:class op:AminoAcidType ;
588
+ sh:minCount 1 ;
589
+ sh:maxCount 1 ;
590
+ sh:message "An amino acid monograph must specify its amino acid type."@en
591
+ ] ;
592
+
593
+ sh:property [
594
+ sh:path op:essentialAminoAcid ;
595
+ sh:datatype xsd:boolean ;
596
+ sh:maxCount 1 ;
597
+ sh:severity sh:Info ;
598
+ sh:message "An amino acid monograph may indicate if it is essential."@en
599
+ ] ;
600
+
601
+ sh:property [
602
+ sh:path op:stereochemistry ;
603
+ sh:datatype xsd:string ;
604
+ sh:maxCount 1 ;
605
+ sh:severity sh:Warning ;
606
+ sh:message "An amino acid monograph should specify stereochemistry (L, D, DL)."@en
607
+ ] .
608
+
609
+ # =============================================================================
610
+ # MINERAL SUBSTANCE MONOGRAPH SHAPE
611
+ # =============================================================================
612
+
613
+ shape:MineralSubstanceMonographShape
614
+ a sh:NodeShape ;
615
+ sh:targetClass op:MineralSubstanceMonograph ;
616
+
617
+ # Inherits all constraints from PharmacopoeiaMonograph
618
+ sh:and ( shape:PharmacopoeiaMonographShape ) ;
619
+
620
+ # Required mineral identification properties
621
+ sh:property [
622
+ sh:path op:mineralFormula ;
623
+ sh:datatype xsd:string ;
624
+ sh:minCount 1 ;
625
+ sh:maxCount 1 ;
626
+ sh:message "A mineral substance monograph must have a chemical formula."@en
627
+ ] ;
628
+
629
+ sh:property [
630
+ sh:path op:mineralType ;
631
+ sh:class op:MineralType ;
632
+ sh:maxCount 1 ;
633
+ sh:severity sh:Warning ;
634
+ sh:message "A mineral substance monograph should specify its mineral type."@en
635
+ ] ;
636
+
637
+ # Mineral-specific properties
638
+ sh:property [
639
+ sh:path op:mineralSource ;
640
+ sh:datatype rdf:langString ;
641
+ sh:maxCount 1 ;
642
+ sh:severity sh:Info ;
643
+ sh:message "A mineral substance monograph may specify the natural source."@en
644
+ ] ;
645
+
646
+ sh:property [
647
+ sh:path op:elementalComposition ;
648
+ sh:datatype rdf:langString ;
649
+ sh:maxCount 1 ;
650
+ sh:severity sh:Info ;
651
+ sh:message "A mineral substance monograph may specify elemental composition."@en
652
+ ] .
653
+
654
+ # =============================================================================
655
+ # BIOLOGICAL SUBSTANCE MONOGRAPH SHAPE
656
+ # =============================================================================
657
+
658
+ shape:BiologicalSubstanceMonographShape
659
+ a sh:NodeShape ;
660
+ sh:targetClass op:BiologicalSubstanceMonograph ;
661
+
662
+ # Inherits all constraints from PharmacopoeiaMonograph
663
+ sh:and ( shape:PharmacopoeiaMonographShape ) ;
664
+
665
+ # Required biological identification properties
666
+ sh:property [
667
+ sh:path op:biologicalSourceType ;
668
+ sh:class op:BiologicalSourceType ;
669
+ sh:minCount 1 ;
670
+ sh:maxCount 1 ;
671
+ sh:message "A biological substance monograph must specify its biological source type."@en
672
+ ] ;
673
+
674
+ sh:property [
675
+ sh:path op:biologicalOrigin ;
676
+ sh:datatype rdf:langString ;
677
+ sh:maxCount 1 ;
678
+ sh:severity sh:Warning ;
679
+ sh:message "A biological substance monograph should specify biological origin (animal, plant, microbial)."@en
680
+ ] ;
681
+
682
+ # Biological-specific properties
683
+ sh:property [
684
+ sh:path op:activityUnit ;
685
+ sh:datatype rdf:langString ;
686
+ sh:maxCount 1 ;
687
+ sh:severity sh:Warning ;
688
+ sh:message "A biological substance monograph should specify activity units (e.g., Units/mg)."@en
689
+ ] ;
690
+
691
+ sh:property [
692
+ sh:path op:sourceOrganism ;
693
+ sh:datatype rdf:langString ;
694
+ sh:maxCount 1 ;
695
+ sh:severity sh:Info ;
696
+ sh:message "A biological substance monograph may specify the source organism."@en
697
+ ] .
698
+
699
+ # =============================================================================
700
+ # ENZYME PREPARATION MONOGRAPH SHAPE
701
+ # =============================================================================
702
+
703
+ shape:EnzymePreparationMonographShape
704
+ a sh:NodeShape ;
705
+ sh:targetClass op:EnzymePreparationMonograph ;
706
+
707
+ # Inherits all constraints from BiologicalSubstanceMonograph
708
+ sh:and ( shape:BiologicalSubstanceMonographShape ) ;
709
+
710
+ # Enzyme-specific properties
711
+ sh:property [
712
+ sh:path op:enzymeCommissionNumber ;
713
+ sh:datatype xsd:string ;
714
+ sh:minCount 1 ;
715
+ sh:maxCount 1 ;
716
+ sh:message "An enzyme preparation monograph must have an EC number."@en
717
+ ] ;
718
+
719
+ sh:property [
720
+ sh:path op:enzymeActivity ;
721
+ sh:datatype rdf:langString ;
722
+ sh:minCount 1 ;
723
+ sh:maxCount 1 ;
724
+ sh:message "An enzyme preparation monograph must specify enzyme activity."@en
725
+ ] ;
726
+
727
+ sh:property [
728
+ sh:path op:optimalPH ;
729
+ sh:datatype xsd:decimal ;
730
+ sh:maxCount 1 ;
731
+ sh:severity sh:Info ;
732
+ sh:message "An enzyme preparation monograph may specify optimal pH."@en
733
+ ] ;
734
+
735
+ sh:property [
736
+ sh:path op:optimalTemperature ;
737
+ sh:datatype xsd:decimal ;
738
+ sh:maxCount 1 ;
739
+ sh:severity sh:Info ;
740
+ sh:message "An enzyme preparation monograph may specify optimal temperature."@en
741
+ ] .
742
+
743
+ # =============================================================================
744
+ # HORMONE PREPARATION MONOGRAPH SHAPE
745
+ # =============================================================================
746
+
747
+ shape:HormonePreparationMonographShape
748
+ a sh:NodeShape ;
749
+ sh:targetClass op:HormonePreparationMonograph ;
750
+
751
+ # Inherits all constraints from BiologicalSubstanceMonograph
752
+ sh:and ( shape:BiologicalSubstanceMonographShape ) ;
753
+
754
+ # Hormone-specific properties
755
+ sh:property [
756
+ sh:path op:hormoneType ;
757
+ sh:class op:HormoneType ;
758
+ sh:minCount 1 ;
759
+ sh:maxCount 1 ;
760
+ sh:message "A hormone preparation monograph must specify its hormone type."@en
761
+ ] ;
762
+
763
+ sh:property [
764
+ sh:path op:biologicalPotency ;
765
+ sh:datatype rdf:langString ;
766
+ sh:maxCount 1 ;
767
+ sh:severity sh:Warning ;
768
+ sh:message "A hormone preparation monograph should specify biological potency."@en
769
+ ] .
770
+
771
+ # =============================================================================
772
+ # FORMULATION MONOGRAPH SHAPE
773
+ # =============================================================================
774
+
775
+ shape:FormulationMonographShape
776
+ a sh:NodeShape ;
777
+ sh:targetClass op:FormulationMonograph ;
778
+
779
+ # Inherits all constraints from PharmacopoeiaMonograph
780
+ sh:and ( shape:PharmacopoeiaMonographShape ) ;
781
+
782
+ # Required formulation properties
783
+ sh:property [
784
+ sh:path op:dosageForm ;
785
+ sh:class op:DosageForm ;
786
+ sh:minCount 1 ;
787
+ sh:maxCount 1 ;
788
+ sh:message "A formulation monograph must have exactly one dosage form."@en
789
+ ] ;
790
+
791
+ sh:property [
792
+ sh:path op:hasComponent ;
793
+ sh:class op:FormulationComponent ;
794
+ sh:minCount 1 ;
795
+ sh:node shape:FormulationComponentShape ;
796
+ sh:message "A formulation monograph must have at least one component."@en
797
+ ] ;
798
+
799
+ # Optional formulation properties
800
+ sh:property [
801
+ sh:path op:routeOfAdministration ;
802
+ sh:class op:RouteOfAdministration ;
803
+ sh:maxCount 1 ;
804
+ sh:severity sh:Warning ;
805
+ sh:message "A formulation monograph should specify route of administration."@en
806
+ ] ;
807
+
808
+ sh:property [
809
+ sh:path op:packSize ;
810
+ sh:datatype xsd:string ;
811
+ sh:maxCount 1 ;
812
+ sh:severity sh:Info ;
813
+ sh:message "A formulation monograph may specify pack size."@en
814
+ ] ;
815
+
816
+ sh:property [
817
+ sh:path op:shelfLife ;
818
+ sh:datatype xsd:string ;
819
+ sh:maxCount 1 ;
820
+ sh:severity sh:Info ;
821
+ sh:message "A formulation monograph may specify shelf life."@en
822
+ ] .
823
+
824
+ # =============================================================================
825
+ # FORMULATION COMPONENT SHAPE
826
+ # =============================================================================
827
+
828
+ shape:FormulationComponentShape
829
+ a sh:NodeShape ;
830
+ sh:targetClass op:FormulationComponent ;
831
+
832
+ # Required component properties
833
+ sh:property [
834
+ sh:path op:componentSubstance ;
835
+ sh:datatype xsd:anyURI ;
836
+ sh:minCount 1 ;
837
+ sh:maxCount 1 ;
838
+ sh:message "A formulation component must reference exactly one substance."@en
839
+ ] ;
840
+
841
+ sh:property [
842
+ sh:path op:componentRole ;
843
+ sh:class op:ComponentRole ;
844
+ sh:minCount 1 ;
845
+ sh:maxCount 1 ;
846
+ sh:message "A formulation component must have exactly one role."@en
847
+ ] ;
848
+
849
+ # Component quantity (required for active ingredients)
850
+ sh:property [
851
+ sh:path op:componentQuantity ;
852
+ sh:datatype xsd:decimal ;
853
+ sh:maxCount 1 ;
854
+ sh:severity sh:Warning ;
855
+ sh:message "A formulation component should specify quantity."@en
856
+ ] ;
857
+
858
+ sh:property [
859
+ sh:path op:componentUnit ;
860
+ sh:class op:Unit ;
861
+ sh:maxCount 1 ;
862
+ sh:severity sh:Info ;
863
+ sh:message "A formulation component may specify quantity unit."@en
864
+ ] ;
865
+
866
+ # Optional component properties
867
+ sh:property [
868
+ sh:path op:componentStrength ;
869
+ sh:datatype xsd:string ;
870
+ sh:maxCount 1 ;
871
+ sh:severity sh:Info ;
872
+ sh:message "A formulation component may specify strength (e.g., '500 mg per tablet')."@en
873
+ ] ;
874
+
875
+ sh:property [
876
+ sh:path op:componentPercentage ;
877
+ sh:datatype xsd:decimal ;
878
+ sh:maxCount 1 ;
879
+ sh:severity sh:Info ;
880
+ sh:message "A formulation component may specify percentage in formulation."@en
881
+ ] .
882
+
883
+ # =============================================================================
884
+ # MELTING POINT SPECIFICATION SHAPE
885
+ # =============================================================================
886
+
887
+ shape:MeltingPointSpecificationShape
888
+ a sh:NodeShape ;
889
+ sh:targetClass op:MeltingPointSpecification ;
890
+
891
+ sh:and ( shape:TestSpecificationShape ) ;
892
+
893
+ sh:property [
894
+ sh:path op:meltingPointRange ;
895
+ sh:datatype xsd:string ;
896
+ sh:minCount 1 ;
897
+ sh:maxCount 1 ;
898
+ sh:message "A melting point specification must specify a temperature range."@en
899
+ ] ;
900
+
901
+ sh:property [
902
+ sh:path op:temperatureUnit ;
903
+ sh:class op:TemperatureUnit ;
904
+ sh:maxCount 1 ;
905
+ sh:severity sh:Warning ;
906
+ sh:message "A melting point specification should specify temperature unit."@en
907
+ ] .
908
+
909
+ # =============================================================================
910
+ # SPECIFIC ROTATION SPECIFICATION SHAPE
911
+ # =============================================================================
912
+
913
+ shape:SpecificRotationSpecificationShape
914
+ a sh:NodeShape ;
915
+ sh:targetClass op:SpecificRotationSpecification ;
916
+
917
+ sh:and ( shape:TestSpecificationShape ) ;
918
+
919
+ sh:property [
920
+ sh:path op:rotationRange ;
921
+ sh:datatype xsd:string ;
922
+ sh:minCount 1 ;
923
+ sh:maxCount 1 ;
924
+ sh:message "A specific rotation specification must specify a rotation range."@en
925
+ ] ;
926
+
927
+ sh:property [
928
+ sh:path op:measurementConditions ;
929
+ sh:datatype rdf:langString ;
930
+ sh:maxCount 1 ;
931
+ sh:severity sh:Warning ;
932
+ sh:message "A specific rotation specification should specify measurement conditions (temperature, wavelength, solvent)."@en
933
+ ] .
934
+
935
+ # =============================================================================
936
+ # LOSS ON DRYING SPECIFICATION SHAPE
937
+ # =============================================================================
938
+
939
+ shape:LossOnDryingSpecificationShape
940
+ a sh:NodeShape ;
941
+ sh:targetClass op:LossOnDryingSpecification ;
942
+
943
+ sh:and ( shape:TestSpecificationShape ) ;
944
+
945
+ sh:property [
946
+ sh:path op:dryingConditions ;
947
+ sh:datatype rdf:langString ;
948
+ sh:minCount 1 ;
949
+ sh:maxCount 1 ;
950
+ sh:message "A loss on drying specification must specify drying conditions."@en
951
+ ] ;
952
+
953
+ sh:property [
954
+ sh:path op:limit ;
955
+ sh:class op:Limit ;
956
+ sh:minCount 1 ;
957
+ sh:node shape:LimitShape ;
958
+ sh:message "A loss on drying specification must have a limit."@en
959
+ ] .
960
+
961
+ # =============================================================================
962
+ # RESIDUE ON IGNITION SPECIFICATION SHAPE
963
+ # =============================================================================
964
+
965
+ shape:ResidueOnIgnitionSpecificationShape
966
+ a sh:NodeShape ;
967
+ sh:targetClass op:ResidueOnIgnitionSpecification ;
968
+
969
+ sh:and ( shape:TestSpecificationShape ) ;
970
+
971
+ sh:property [
972
+ sh:path op:ignitionConditions ;
973
+ sh:datatype rdf:langString ;
974
+ sh:minCount 1 ;
975
+ sh:maxCount 1 ;
976
+ sh:message "A residue on ignition specification must specify ignition conditions."@en
977
+ ] ;
978
+
979
+ sh:property [
980
+ sh:path op:limit ;
981
+ sh:class op:Limit ;
982
+ sh:minCount 1 ;
983
+ sh:node shape:LimitShape ;
984
+ sh:message "A residue on ignition specification must have a limit."@en
985
+ ] .
986
+
987
+ # =============================================================================
988
+ # PH SPECIFICATION SHAPE
989
+ # =============================================================================
990
+
991
+ shape:PHSpecificationShape
992
+ a sh:NodeShape ;
993
+ sh:targetClass op:PHSpecification ;
994
+
995
+ sh:and ( shape:TestSpecificationShape ) ;
996
+
997
+ sh:property [
998
+ sh:path op:phRange ;
999
+ sh:datatype xsd:string ;
1000
+ sh:minCount 1 ;
1001
+ sh:maxCount 1 ;
1002
+ sh:message "A pH specification must specify a pH range."@en
1003
+ ] ;
1004
+
1005
+ sh:property [
1006
+ sh:path op:solutionConditions ;
1007
+ sh:datatype rdf:langString ;
1008
+ sh:maxCount 1 ;
1009
+ sh:severity sh:Warning ;
1010
+ sh:message "A pH specification should specify solution conditions (concentration, solvent)."@en
1011
+ ] .
1012
+
1013
+ # =============================================================================
1014
+ # DISSOLUTION SPECIFICATION SHAPE
1015
+ # =============================================================================
1016
+
1017
+ shape:DissolutionSpecificationShape
1018
+ a sh:NodeShape ;
1019
+ sh:targetClass op:DissolutionSpecification ;
1020
+
1021
+ sh:and ( shape:TestSpecificationShape ) ;
1022
+
1023
+ sh:property [
1024
+ sh:path op:dissolutionMedium ;
1025
+ sh:datatype rdf:langString ;
1026
+ sh:minCount 1 ;
1027
+ sh:maxCount 1 ;
1028
+ sh:message "A dissolution specification must specify the dissolution medium."@en
1029
+ ] ;
1030
+
1031
+ sh:property [
1032
+ sh:path op:dissolutionApparatus ;
1033
+ sh:datatype xsd:string ;
1034
+ sh:minCount 1 ;
1035
+ sh:maxCount 1 ;
1036
+ sh:message "A dissolution specification must specify the apparatus type."@en
1037
+ ] ;
1038
+
1039
+ sh:property [
1040
+ sh:path op:dissolutionTime ;
1041
+ sh:datatype xsd:string ;
1042
+ sh:minCount 1 ;
1043
+ sh:maxCount 1 ;
1044
+ sh:message "A dissolution specification must specify time points."@en
1045
+ ] ;
1046
+
1047
+ sh:property [
1048
+ sh:path op:dissolutionLimit ;
1049
+ sh:datatype xsd:string ;
1050
+ sh:minCount 1 ;
1051
+ sh:maxCount 1 ;
1052
+ sh:message "A dissolution specification must specify the dissolution limit (Q value)."@en
1053
+ ] .
1054
+
1055
+ # =============================================================================
1056
+ # CONTENT UNIFORMITY SPECIFICATION SHAPE
1057
+ # =============================================================================
1058
+
1059
+ shape:ContentUniformitySpecificationShape
1060
+ a sh:NodeShape ;
1061
+ sh:targetClass op:ContentUniformitySpecification ;
1062
+
1063
+ sh:and ( shape:TestSpecificationShape ) ;
1064
+
1065
+ sh:property [
1066
+ sh:path op:acceptanceValue ;
1067
+ sh:datatype xsd:decimal ;
1068
+ sh:maxCount 1 ;
1069
+ sh:severity sh:Warning ;
1070
+ sh:message "A content uniformity specification should specify acceptance value (AV)."@en
1071
+ ] ;
1072
+
1073
+ sh:property [
1074
+ sh:path op:referenceMethod ;
1075
+ sh:class op:HarmonizedMethod ;
1076
+ sh:maxCount 1 ;
1077
+ sh:severity sh:Info ;
1078
+ sh:message "A content uniformity specification may reference a harmonized method."@en
1079
+ ] .
1080
+
1081
+ # =============================================================================
1082
+ # TEST CLASS HIERARCHY SHAPES (from data-japan-pharmacopia)
1083
+ # =============================================================================
1084
+
1085
+ shape:TestShape
1086
+ a sh:NodeShape ;
1087
+ sh:targetClass op:Test ;
1088
+
1089
+ sh:property [
1090
+ sh:path op:testName ;
1091
+ sh:datatype rdf:langString ;
1092
+ sh:minCount 1 ;
1093
+ sh:maxCount 1 ;
1094
+ sh:message "A test must have exactly one test name."@en
1095
+ ] ;
1096
+
1097
+ sh:property [
1098
+ sh:path op:usesTestMethod ;
1099
+ sh:class op:HarmonizedMethod ;
1100
+ sh:maxCount 1 ;
1101
+ sh:severity sh:Info ;
1102
+ sh:message "A test may reference a harmonized method."@en
1103
+ ] ;
1104
+
1105
+ sh:property [
1106
+ sh:path op:testDescription ;
1107
+ sh:datatype rdf:langString ;
1108
+ sh:severity sh:Info ;
1109
+ sh:message "A test may have a description of the test procedure."@en
1110
+ ] .
1111
+
1112
+ shape:IdentificationTestShape
1113
+ a sh:NodeShape ;
1114
+ sh:targetClass op:IdentificationTest ;
1115
+
1116
+ sh:and ( shape:TestShape ) ;
1117
+
1118
+ sh:property [
1119
+ sh:path op:identificationMethod ;
1120
+ sh:datatype xsd:string ;
1121
+ sh:maxCount 1 ;
1122
+ sh:severity sh:Warning ;
1123
+ sh:message "An identification test should specify the method (e.g., TLC, UV, IR)."@en
1124
+ ] ;
1125
+
1126
+ sh:property [
1127
+ sh:path op:expectedResult ;
1128
+ sh:datatype xsd:string ;
1129
+ sh:maxCount 1 ;
1130
+ sh:severity sh:Warning ;
1131
+ sh:message "An identification test should specify the expected result."@en
1132
+ ] .
1133
+
1134
+ shape:PurityTestShape
1135
+ a sh:NodeShape ;
1136
+ sh:targetClass op:PurityTest ;
1137
+
1138
+ sh:and ( shape:TestShape ) ;
1139
+
1140
+ sh:property [
1141
+ sh:path op:impurityType ;
1142
+ sh:datatype rdf:langString ;
1143
+ sh:minCount 1 ;
1144
+ sh:maxCount 1 ;
1145
+ sh:message "A purity test must specify the impurity type."@en
1146
+ ] ;
1147
+
1148
+ sh:property [
1149
+ sh:path op:limit ;
1150
+ sh:class op:Limit ;
1151
+ sh:maxCount 1 ;
1152
+ sh:severity sh:Warning ;
1153
+ sh:message "A purity test should have a limit."@en
1154
+ ] .
1155
+
1156
+ shape:LimitTestShape
1157
+ a sh:NodeShape ;
1158
+ sh:targetClass op:LimitTest ;
1159
+
1160
+ sh:and ( shape:TestShape ) ;
1161
+
1162
+ sh:property [
1163
+ sh:path op:limit ;
1164
+ sh:class op:Limit ;
1165
+ sh:minCount 1 ;
1166
+ sh:maxCount 1 ;
1167
+ sh:message "A limit test must have a limit."@en
1168
+ ] .
1169
+
1170
+ shape:AssayTestShape
1171
+ a sh:NodeShape ;
1172
+ sh:targetClass op:AssayTest ;
1173
+
1174
+ sh:and ( shape:TestShape ) ;
1175
+
1176
+ sh:property [
1177
+ sh:path op:assayTarget ;
1178
+ sh:datatype rdf:langString ;
1179
+ sh:minCount 1 ;
1180
+ sh:maxCount 1 ;
1181
+ sh:message "An assay test must specify the target compound or parameter."@en
1182
+ ] ;
1183
+
1184
+ sh:property [
1185
+ sh:path op:limit ;
1186
+ sh:class op:Limit ;
1187
+ sh:minCount 1 ;
1188
+ sh:maxCount 1 ;
1189
+ sh:message "An assay test must have a limit."@en
1190
+ ] .
1191
+
1192
+ # =============================================================================
1193
+ # PREPARATION METHOD SHAPE (from data-japan-pharmacopia)
1194
+ # =============================================================================
1195
+
1196
+ shape:PreparationMethodShape
1197
+ a sh:NodeShape ;
1198
+ sh:targetClass op:PreparationMethod ;
1199
+
1200
+ sh:property [
1201
+ sh:path op:methodLabel ;
1202
+ sh:datatype rdf:langString ;
1203
+ sh:minCount 1 ;
1204
+ sh:maxCount 1 ;
1205
+ sh:message "A preparation method must have a label."@en
1206
+ ] ;
1207
+
1208
+ sh:property [
1209
+ sh:path op:methodDescription ;
1210
+ sh:datatype rdf:langString ;
1211
+ sh:maxCount 1 ;
1212
+ sh:severity sh:Warning ;
1213
+ sh:message "A preparation method should have a description."@en
1214
+ ] ;
1215
+
1216
+ sh:property [
1217
+ sh:path op:hasIngredientItem ;
1218
+ sh:class op:Ingredient ;
1219
+ sh:minCount 1 ;
1220
+ sh:node shape:IngredientShape ;
1221
+ sh:message "A preparation method must have at least one ingredient."@en
1222
+ ] .
1223
+
1224
+ # =============================================================================
1225
+ # INGREDIENT SHAPE (from data-japan-pharmacopia)
1226
+ # =============================================================================
1227
+
1228
+ shape:IngredientShape
1229
+ a sh:NodeShape ;
1230
+ sh:targetClass op:Ingredient ;
1231
+
1232
+ sh:property [
1233
+ sh:path op:usesCrudeDrug ;
1234
+ sh:class op:CrudeDrugMonograph ;
1235
+ sh:minCount 1 ;
1236
+ sh:maxCount 1 ;
1237
+ sh:message "An ingredient must reference exactly one crude drug."@en
1238
+ ] ;
1239
+
1240
+ sh:property [
1241
+ sh:path op:ingredientAmount ;
1242
+ sh:datatype xsd:decimal ;
1243
+ sh:minCount 1 ;
1244
+ sh:maxCount 1 ;
1245
+ sh:message "An ingredient must have an amount."@en
1246
+ ] ;
1247
+
1248
+ sh:property [
1249
+ sh:path op:ingredientAmountUnit ;
1250
+ sh:datatype xsd:string ;
1251
+ sh:maxCount 1 ;
1252
+ sh:severity sh:Warning ;
1253
+ sh:message "An ingredient should have an amount unit."@en
1254
+ ] ;
1255
+
1256
+ sh:property [
1257
+ sh:path op:ingredientRatio ;
1258
+ sh:datatype xsd:decimal ;
1259
+ sh:maxCount 1 ;
1260
+ sh:severity sh:Info ;
1261
+ sh:message "An ingredient may have a ratio in the formula."@en
1262
+ ] .
1263
+
1264
+ # =============================================================================
1265
+ # POWDERED CRUDE DRUG SHAPE (from data-japan-pharmacopia)
1266
+ # =============================================================================
1267
+
1268
+ shape:PowderedCrudeDrugShape
1269
+ a sh:NodeShape ;
1270
+ sh:targetClass op:PowderedCrudeDrug ;
1271
+
1272
+ # Inherits all constraints from CrudeDrugMonograph
1273
+ sh:and ( shape:CrudeDrugMonographShape ) ;
1274
+
1275
+ sh:property [
1276
+ sh:path op:isPowderedFormOf ;
1277
+ sh:class op:CrudeDrugMonograph ;
1278
+ sh:minCount 1 ;
1279
+ sh:maxCount 1 ;
1280
+ sh:message "A powdered crude drug must reference its source crude drug."@en
1281
+ ] .
1282
+
1283
+ # =============================================================================
1284
+ # EXTRACT SHAPE (with preparation method support)
1285
+ # =============================================================================
1286
+
1287
+ shape:ExtractShape
1288
+ a sh:NodeShape ;
1289
+ sh:targetClass op:Extract ;
1290
+
1291
+ # Inherits all constraints from PharmacopoeiaMonograph
1292
+ sh:and ( shape:PharmacopoeiaMonographShape ) ;
1293
+
1294
+ sh:property [
1295
+ sh:path op:extractionRatio ;
1296
+ sh:datatype xsd:string ;
1297
+ sh:maxCount 1 ;
1298
+ sh:severity sh:Info ;
1299
+ sh:message "An extract may have an extraction ratio."@en
1300
+ ] ;
1301
+
1302
+ sh:property [
1303
+ sh:path op:extractionSolvent ;
1304
+ sh:datatype rdf:langString ;
1305
+ sh:maxCount 1 ;
1306
+ sh:severity sh:Info ;
1307
+ sh:message "An extract may specify the extraction solvent."@en
1308
+ ] ;
1309
+
1310
+ sh:property [
1311
+ sh:path op:hasPreparationMethod ;
1312
+ sh:class op:PreparationMethod ;
1313
+ sh:maxCount 1 ;
1314
+ sh:node shape:PreparationMethodShape ;
1315
+ sh:severity sh:Warning ;
1316
+ sh:message "An extract should have a preparation method."@en
1317
+ ] ;
1318
+
1319
+ sh:property [
1320
+ sh:path op:hasIngredient ;
1321
+ sh:class op:CrudeDrugMonograph ;
1322
+ sh:severity sh:Info ;
1323
+ sh:message "An extract may have ingredients (for multi-herb extracts)."@en
1324
+ ] .