adiwg-mdtranslator 2.21.0.pre.beta.0 → 2.21.0.pre.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +1 -1
  3. data/DCAT-US.md +67 -0
  4. data/Gemfile.lock +5 -5
  5. data/README.md +21 -0
  6. data/Rakefile +1 -0
  7. data/adiwg-mdtranslator.gemspec +2 -2
  8. data/lib/adiwg/mdtranslator/internal/internal_metadata_obj.rb +1 -0
  9. data/lib/adiwg/mdtranslator/readers/fgdc/modules/module_dataQuality.rb +27 -37
  10. data/lib/adiwg/mdtranslator/readers/mdJson/modules/module_dataDictionary.rb +8 -0
  11. data/lib/adiwg/mdtranslator/version.rb +1 -1
  12. data/lib/adiwg/mdtranslator/writers/dcat_us/dcat_us_writer.rb +98 -0
  13. data/lib/adiwg/mdtranslator/writers/dcat_us/readme.md +10 -0
  14. data/lib/adiwg/mdtranslator/writers/dcat_us/sections/dcat_us_access_level.rb +55 -0
  15. data/lib/adiwg/mdtranslator/writers/dcat_us/sections/dcat_us_access_url.rb +17 -0
  16. data/lib/adiwg/mdtranslator/writers/dcat_us/sections/dcat_us_accrualPeriodicity.rb +45 -0
  17. data/lib/adiwg/mdtranslator/writers/dcat_us/sections/dcat_us_bureau_code.rb +33 -0
  18. data/lib/adiwg/mdtranslator/writers/dcat_us/sections/dcat_us_contact_point.rb +29 -0
  19. data/lib/adiwg/mdtranslator/writers/dcat_us/sections/dcat_us_dcat_us.rb +104 -0
  20. data/lib/adiwg/mdtranslator/writers/dcat_us/sections/dcat_us_described_by.rb +29 -0
  21. data/lib/adiwg/mdtranslator/writers/dcat_us/sections/dcat_us_described_by_type.rb +33 -0
  22. data/lib/adiwg/mdtranslator/writers/dcat_us/sections/dcat_us_description.rb +19 -0
  23. data/lib/adiwg/mdtranslator/writers/dcat_us/sections/dcat_us_distribution.rb +59 -0
  24. data/lib/adiwg/mdtranslator/writers/dcat_us/sections/dcat_us_download_url.rb +17 -0
  25. data/lib/adiwg/mdtranslator/writers/dcat_us/sections/dcat_us_identifier.rb +29 -0
  26. data/lib/adiwg/mdtranslator/writers/dcat_us/sections/dcat_us_is_part_of.rb +27 -0
  27. data/lib/adiwg/mdtranslator/writers/dcat_us/sections/dcat_us_issued.rb +19 -0
  28. data/lib/adiwg/mdtranslator/writers/dcat_us/sections/dcat_us_keyword.rb +19 -0
  29. data/lib/adiwg/mdtranslator/writers/dcat_us/sections/dcat_us_landing_page.rb +27 -0
  30. data/lib/adiwg/mdtranslator/writers/dcat_us/sections/dcat_us_language.rb +23 -0
  31. data/lib/adiwg/mdtranslator/writers/dcat_us/sections/dcat_us_license.rb +18 -0
  32. data/lib/adiwg/mdtranslator/writers/dcat_us/sections/dcat_us_media_type.rb +17 -0
  33. data/lib/adiwg/mdtranslator/writers/dcat_us/sections/dcat_us_modified.rb +29 -0
  34. data/lib/adiwg/mdtranslator/writers/dcat_us/sections/dcat_us_primaryITInvestmentUII.rb +19 -0
  35. data/lib/adiwg/mdtranslator/writers/dcat_us/sections/dcat_us_program_code.rb +33 -0
  36. data/lib/adiwg/mdtranslator/writers/dcat_us/sections/dcat_us_publisher.rb +74 -0
  37. data/lib/adiwg/mdtranslator/writers/dcat_us/sections/dcat_us_references.rb +50 -0
  38. data/lib/adiwg/mdtranslator/writers/dcat_us/sections/dcat_us_rights.rb +32 -0
  39. data/lib/adiwg/mdtranslator/writers/dcat_us/sections/dcat_us_spatial.rb +32 -0
  40. data/lib/adiwg/mdtranslator/writers/dcat_us/sections/dcat_us_system_of_records.rb +28 -0
  41. data/lib/adiwg/mdtranslator/writers/dcat_us/sections/dcat_us_temporal.rb +40 -0
  42. data/lib/adiwg/mdtranslator/writers/dcat_us/sections/dcat_us_theme.rb +28 -0
  43. data/lib/adiwg/mdtranslator/writers/dcat_us/version.rb +14 -0
  44. data/lib/adiwg/mdtranslator/writers/fgdc/classes/class_dataQuality.rb +133 -185
  45. data/lib/adiwg/mdtranslator/writers/fgdc/classes/class_spatialDomain.rb +1 -1
  46. data/lib/adiwg/mdtranslator/writers/iso19115_3/classes/class_acquisition.rb +103 -0
  47. data/lib/adiwg/mdtranslator/writers/iso19115_3/classes/class_enumerationList.rb +52 -0
  48. data/lib/adiwg/mdtranslator/writers/iso19115_3/classes/class_environment.rb +82 -0
  49. data/lib/adiwg/mdtranslator/writers/iso19115_3/classes/class_event.rb +123 -0
  50. data/lib/adiwg/mdtranslator/writers/iso19115_3/classes/class_extension.rb +208 -0
  51. data/lib/adiwg/mdtranslator/writers/iso19115_3/classes/class_instrument.rb +92 -0
  52. data/lib/adiwg/mdtranslator/writers/iso19115_3/classes/class_instrumentationEvent.rb +83 -0
  53. data/lib/adiwg/mdtranslator/writers/iso19115_3/classes/class_instrumentationEventList.rb +73 -0
  54. data/lib/adiwg/mdtranslator/writers/iso19115_3/classes/class_mdMetadata.rb +38 -0
  55. data/lib/adiwg/mdtranslator/writers/iso19115_3/classes/class_objective.rb +121 -0
  56. data/lib/adiwg/mdtranslator/writers/iso19115_3/classes/class_operation.rb +131 -0
  57. data/lib/adiwg/mdtranslator/writers/iso19115_3/classes/class_pass.rb +63 -0
  58. data/lib/adiwg/mdtranslator/writers/iso19115_3/classes/class_plan.rb +76 -0
  59. data/lib/adiwg/mdtranslator/writers/iso19115_3/classes/class_platform.rb +102 -0
  60. data/lib/adiwg/mdtranslator/writers/iso19115_3/classes/class_requestedDate.rb +44 -0
  61. data/lib/adiwg/mdtranslator/writers/iso19115_3/classes/class_requirement.rb +111 -0
  62. data/lib/adiwg/mdtranslator/writers/iso19115_3/classes/class_revision.rb +55 -0
  63. data/lib/adiwg/mdtranslator/writers/iso19115_3/classes/class_timePeriod.rb +2 -6
  64. data/lib/adiwg/mdtranslator/writers/mdJson/sections/mdJson_dictionary.rb +1 -0
  65. data/lib/adiwg/mdtranslator/writers/simple_html/sections/html_acquisition.rb +195 -0
  66. data/lib/adiwg/mdtranslator/writers/simple_html/sections/html_allocation.rb +1 -1
  67. data/lib/adiwg/mdtranslator/writers/simple_html/sections/html_body.rb +18 -2
  68. data/lib/adiwg/mdtranslator/writers/simple_html/sections/html_citation.rb +8 -8
  69. data/lib/adiwg/mdtranslator/writers/simple_html/sections/html_dataQualityReport.rb +3 -3
  70. data/lib/adiwg/mdtranslator/writers/simple_html/sections/html_environment.rb +58 -0
  71. data/lib/adiwg/mdtranslator/writers/simple_html/sections/html_event.rb +121 -0
  72. data/lib/adiwg/mdtranslator/writers/simple_html/sections/html_geographicExtent.rb +1 -1
  73. data/lib/adiwg/mdtranslator/writers/simple_html/sections/html_instrument.rb +98 -0
  74. data/lib/adiwg/mdtranslator/writers/simple_html/sections/html_instrumentationEvent.rb +84 -0
  75. data/lib/adiwg/mdtranslator/writers/simple_html/sections/html_instrumentationEventList.rb +90 -0
  76. data/lib/adiwg/mdtranslator/writers/simple_html/sections/html_lineage.rb +4 -4
  77. data/lib/adiwg/mdtranslator/writers/simple_html/sections/html_maintenance.rb +4 -4
  78. data/lib/adiwg/mdtranslator/writers/simple_html/sections/html_medium.rb +2 -2
  79. data/lib/adiwg/mdtranslator/writers/simple_html/sections/html_metadataInfo.rb +4 -4
  80. data/lib/adiwg/mdtranslator/writers/simple_html/sections/html_objective.rb +155 -0
  81. data/lib/adiwg/mdtranslator/writers/simple_html/sections/html_operation.rb +178 -0
  82. data/lib/adiwg/mdtranslator/writers/simple_html/sections/html_pass.rb +72 -0
  83. data/lib/adiwg/mdtranslator/writers/simple_html/sections/html_plan.rb +93 -0
  84. data/lib/adiwg/mdtranslator/writers/simple_html/sections/html_platform.rb +117 -0
  85. data/lib/adiwg/mdtranslator/writers/simple_html/sections/html_releasability.rb +1 -1
  86. data/lib/adiwg/mdtranslator/writers/simple_html/sections/html_requestedDate.rb +33 -0
  87. data/lib/adiwg/mdtranslator/writers/simple_html/sections/html_requirement.rb +139 -0
  88. data/lib/adiwg/mdtranslator/writers/simple_html/sections/html_resourceInfo.rb +5 -5
  89. data/lib/adiwg/mdtranslator/writers/simple_html/sections/html_responsibility.rb +1 -1
  90. data/lib/adiwg/mdtranslator/writers/simple_html/sections/html_revision.rb +55 -0
  91. data/lib/adiwg/mdtranslator/writers/simple_html/sections/html_spatialRepresentation.rb +4 -4
  92. data/lib/adiwg/mdtranslator/writers/simple_html/sections/html_taxonomy.rb +1 -1
  93. data/lib/adiwg/mdtranslator/writers/simple_html/sections/html_timeInstant.rb +1 -1
  94. data/lib/adiwg/mdtranslator/writers/simple_html/sections/html_timePeriod.rb +5 -5
  95. data/lib/adiwg/mdtranslator/writers/simple_html/sections/html_transferOption.rb +2 -2
  96. data/lib/adiwg/mdtranslator/writers/simple_html/sections/html_usage.rb +5 -5
  97. data/lib/adiwg/mdtranslator/writers/simple_html/sections/html_vectorRepresentation.rb +2 -2
  98. data/lib/adiwg/mdtranslator_cli.rb +1 -1
  99. metadata +69 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 24a46249aaab639bcbfcf96546503546a9474db0aaf8d3d9136190cbd7ae2c19
4
- data.tar.gz: da85309bcd6c126043a653d5e436535d7d29c4eb2107a416acb1cdc4575d3696
3
+ metadata.gz: b6d6f205260d7cd279df45c873810e05a328d4fd8915be617b29c4c57044af13
4
+ data.tar.gz: fcfc19da4c41bc3b93b528f57122119cc12d8f988e3afc9553f4275f639cd833
5
5
  SHA512:
6
- metadata.gz: 966ff66ba5977d8f190b38535637cf43b0d346291ed81928179814b8bbb081a2967d56bba02f80847525e0f86fce8c0e1d405d71fbd7dcf1338c7cc5e2c2a31c
7
- data.tar.gz: ae9ec9bd0c85646c0b7b99d79adda40be5ea40de1bb14eb133471028a3b9800b86138591abf2e1c87d6c3bc8e5e07741a66f816755558823cdc76697d30b9845
6
+ metadata.gz: '097c2bf2ffdcfc10e63b16d44cdf72fc9e30c0cdebeab4366e07eae6d0c13dc52b782c3882d17516c8843cb19e7cecc2c064aa8e89dd56cbeccb254acae4e8f1'
7
+ data.tar.gz: 14fab38df050287ba08b0337aeaf9ebc4c2e42a113a63709cff0019f7dc3ba761534c35586e055aef57b5b147cfb4571eb466cd5a208f90da431aa3e09742309
@@ -7,7 +7,7 @@ jobs:
7
7
  runs-on: ubuntu-latest
8
8
  steps:
9
9
  - uses: actions/checkout@v4
10
- - uses: ruby/setup-ruby@ec02537da5712d66d4d50a0f33b7eb52773b5ed1
10
+ - uses: ruby/setup-ruby@v1
11
11
  with:
12
12
  ruby-version: "3.1" # Not needed with a .ruby-version file
13
13
  - run: bundle install
data/DCAT-US.md ADDED
@@ -0,0 +1,67 @@
1
+ # DCAT-US - mdTranslator proposed mappings
2
+ ## Quick references
3
+ - DCAT-US [element definitions](https://resources.data.gov/resources/dcat-us/)
4
+ - DCAT-US v1.1 [catalog.json schema](https://resources.data.gov/schemas/dcat-us/v1.1/schema/catalog.json)
5
+ - DCAT-US v1.1 [dataset.json schema](https://resources.data.gov/schemas/dcat-us/v1.1/schema/dataset.json)
6
+ - DCAT-US v1.1 [JSON-LD catalog.json schema](https://resources.data.gov/schemas/dcat-us/v1.1/schema/catalog.jsonld)
7
+ - [Element crosswalks](https://resources.data.gov/resources/podm-field-mapping/#field-mappings) to other standards
8
+
9
+ ## DCAT-US - mdTranslator
10
+
11
+ ### Always (always required)
12
+
13
+ | Field Name | DCAT Name | Condition | mdJson Source |
14
+ | --- | --- | --- | --- |
15
+ | Title | title | exists | citation.title |
16
+ | Description | description | exists | resourceInfo.abstract |
17
+ | Tags | keyword | exists | [resourceInfo.keyword.keyword[0, n] *flatten*] |
18
+ | Last Update | modified | if resourceInfo.citation.date[any].dateType = "lastUpdated" or "lastRevised" or "revision" | resourceInfo.citation.date[most recent] |
19
+ | Publisher | publisher{name} | if citation.responsibleParty.[any].role = "publisher" | contactId -> contact.name where isOrganization IS TRUE |
20
+ | | | if exists resourceDistribution.distributor.contact | [first contact] contactId -> contact.name where isOrganization IS TRUE |
21
+ | Publisher Parent Organization | publisher{subOrganizationOf} | if citation.responsibleParty[any].role = "publisher" and exists contactId -> memberOfOrganization[0] and isOrganization is true | contactId -> contact.name |
22
+ | | | if exists resourceDistribution.distributor.contact and exists contactId -> memberOfOrganization[0] and isOrganization IS TRUE | contactId -> contact.name |
23
+ | Contact Name | contactPoint{fn} | exists | resourceInfo.pointOfContact.parties[0].contactId -> contact.name |
24
+ | Contact Email | contactPoint{email} | exists | resourceInfo.pointOfContact.parties[0].contactId -> contact.eMailList[0] |
25
+ | Unique Identifier | identifier | if resourceInfo.citation.identifier.namespace = "DOI" | resourceInfo.citation.onlineResource.uri |
26
+ | | | if "DOI" within resourceInfo.citation.onlineResource.uri | resourceInfo.citation.onlineResource.uri |
27
+ | Public Access Level | accessLevel | [*extend codelist MD_RestrictionCode to include "public", "restricted public", "non-public"*] <br> if resourceInfo.constraints.legal[any] one of {"public", "restricted public", "non-public"} | resourceInfo.constraints.legal[first]. Also resourceInfo.constraint.security.classification [[MD_ClassificationCode](https://mdtools.adiwg.org/#codes-page?c=iso_classification)] |
28
+ | Bureau Code | bureauCode | | [*extend role codelist to include "bureau", extend namespace codelist to include "bureauCode"*] <br> for each resourceInfo.citation.responsibleParty[any] role = "bureau" <br>contactId -> contact.identifier [*identifier must conform to https://resources.data.gov/schemas/dcat-us/v1.1/omb_bureau_codes.csv*] |
29
+ | Program Code | programCode | | [*add new element of program resourceInfo.programCode, add new codelist of programCode*] <br> resourceInfo.program[0,n] |
30
+
31
+ ### If-Applicable (required if it exists)
32
+
33
+ | Field Name | DCAT Name | Condition | mdJson Source |
34
+ | --- | --- | --- | --- |
35
+ | Distribution | distribution | if exists resourceDistribution[any] and if exists resourceDistribution.distributor[any].transferOption[any].onlineOption[any].uri <br> for each resourceDistribution[0, n] where exists resourceDistribution.distributor.transferOption.onlineOption.uri then <br> {description, accessURL, downloadURL, mediaType, title} |
36
+ | - Description | distribution.description | exists | resourceDistribution.description |
37
+ | - AccessURL | distribution.accessURL | if citation.onlineResources[first occurence].uri [path ends in ".html"] [*required if applicable*] | resourceDistribution.distributor.transferOption.onlineOption.uri |
38
+ | - DownloadURL | dcat.distribution.downloadURL | if citation.onlineResources[first occurence].uri [path does not end in ".html"] [*required if applicable*] |resourceDistribution.distributor.transferOption.onlineOption.uri |
39
+ | - MediaType | distribution.mediaType | [*add codelist of "dataFormat"*] <br> transferOption.distributionFormat.formatSpecification.title [dataFormat] [*dataFormat should conform to: https://www.iana.org/assignments/media-types/media-types.xhtml*] |
40
+ | - Title | distribution.title | exists | resourceDistribution.distributor.transferOption.onlineOption.name |
41
+ | License | license | [*add resourceInfo.constraint.reference to mdEditor*] <br> if exists resourceInfo.constraint.reference[0] | resourceInfo.constraint.reference[0] <br> |
42
+ | | | else | https://creativecommons.org/publicdomain/zero/1.0/ <br> [*allows author to identify a license to use, or default to CC0 if none provided, CC0 would cover international usage as opposed to publicdomain*] <br> [*others: http://www.usa.gov/publicdomain/label/1.0/, http://opendatacommons.org/licenses/pddl/1.0*] |
43
+ | Rights | rights | if constraint.accessLevel in {"restricted public", "non-public"} | resourceInfo.constraint.releasibility.statement + " " + each constraint.releasibility.dessiminationConstraint[0, n] |
44
+ | Endpoint | *removed* | *ignored* | *ignored* |
45
+ | Spatial | spatial | if exists resourceInfo.extents[0].geographicExtents[0].boundingBox | boundingBox.eastLongitude + "," + boundingBox.southLatitude + "," + boundingBox.westLongitude + "," + boundingBox.northLatitude [*decimal degrees*] |
46
+ | | | else | if exists resourceInfo.extents[0].geographicExtents[0].geographicElement[0].type = "point" then <br> geographicElement[0].coordinate[1] + "," + geographicElement[0].coordinate[0] [*lat, long decimal degrees*] |
47
+ | Temporal | temporal | if exists resourceInfo.extent[0].temporalExtent[0] then <br> if exists tempororalExtent[0].timePeriod.startDate and exists temporaralExtent[0].timePeriod.endDate | timePeriod[0].startDate + "/" + timePeriod.endDate |
48
+ | | | if exists tempororalExtent[0].timePeriod.startDate and not exists temporaralExtent[0].timePeriod.endDate | tempororalExtent[0].timePeriod.startDate |
49
+ | | | if not exists temporalExtent[0].timePeriod.startDate and exists temporaralExtent[0].timePeriod.endDate | tempororalExtent[0].timePeriod.endDate <br> [*may need revisiting relative to decision on date only formatting*] |
50
+
51
+ ### No (not required)
52
+
53
+ | Field Name | DCAT Name | Condition | mdJson Source |
54
+ | --- | --- | --- | --- |
55
+ | Release Date | issued | if resourceInfo.citation.date[any].dateType = "publication" or "distributed" | resourceInfo.citation.date[earliest] |
56
+ | Frequency | accrualPeriodicity | | [*ISO codelist MD_maintenanceFrequency can be used and several codes intersect with accrualPeriod codelist they are partially corresponding. A column of ISO8601 code equivalents could be added to MD_maintenanceFrequency to provide the coding expected https://resources.data.gov/schemas/dcat-us/v1.1/iso8601_guidance/#accrualperiodicity, community valuation should be determined*] |
57
+ | Language | language | | [*language codelist could be used but needs to be bound with country corresponding to the RFC 5646 format https://datatracker.ietf.org/doc/html/rfc5646, such as "en-US", community valuation should be determined* |
58
+ | Data Quality | dataQuality | | [*this is a boolean to indicate whether data "conforms" to agency standards, value seems negligble*] |
59
+ | Category | theme | where resourceInfo.keyword[any].thesaurus.title = "ISO Topic Category" | [resourceInfo.keyword.keyword[0, n] *flatten*] |
60
+ | Related Documents | references | | associatedResource[all].resourceCitation.onlineResource[all].uri + additionalDocumentation[all].citation[all].onlineResource[all].uri [*comma separated*]|
61
+ | Homepage URL | landingPage | [*Add code "landingPage" to CI_OnlineFunctionCode*] <br> if resourceInfo.citation.onlineResource[any].function = "landingPage" | resourceInfo.citation.onlineResource.uri |
62
+ | Collection | isPartOf | for each associatedResource[0, n].initiativeType = "collection" and associatedResource.associationType = "collectiveTitle" | associatedResource.resourceCitation[0].uri |
63
+ | System of Records | systemOfRecords | [*Add code "sorn" to DS_InitiativeTypeCode*] <br> for each associatedResource[0, n].initiativeType = "sorn" | associatedResource.resourceCitation[0].uri |
64
+ | Primary IT Investment | primaryITInvestmentUII | | [*Links data to an IT investment identifier relative to Exhibit 53 docs, community valuation should be determined*] |
65
+ | Data Dictionary | describedBy | if dataDictionary.dictionaryIncludedWithResource IS NOT TRUE and citation.onlineResource[0].uri exists | dataDictionary.citation.onlineResource[0].uri |
66
+ | Data Dictionary Type | describedByType | | [*For simplicity, leave blank implying html page, community decision needed whether to support other format types using mime type and in the form of "application/pdf"*]|
67
+ | Data Standard | conformsTo | | [*Currently not able to identify the schema standard the data conforms to, though this has been proposed. Should this be built and there is community decision to support it, then it can be mapped*] |
data/Gemfile.lock CHANGED
@@ -1,9 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- adiwg-mdtranslator (2.21.0.pre.beta.0)
5
- adiwg-mdcodes (= 2.10.0)
6
- adiwg-mdjson_schemas (= 2.10.0.pre.beta.5)
4
+ adiwg-mdtranslator (2.21.0.pre.beta.1)
5
+ adiwg-mdcodes (= 2.10.1)
6
+ adiwg-mdjson_schemas (= 2.10.1)
7
7
  builder (~> 3.2)
8
8
  coderay (~> 1.1)
9
9
  jbuilder (~> 2.5)
@@ -35,9 +35,9 @@ GEM
35
35
  tzinfo (~> 2.0)
36
36
  addressable (2.8.6)
37
37
  public_suffix (>= 2.0.2, < 6.0)
38
- adiwg-mdcodes (2.10.0)
38
+ adiwg-mdcodes (2.10.1)
39
39
  json (~> 2.0)
40
- adiwg-mdjson_schemas (2.10.0.pre.beta.5)
40
+ adiwg-mdjson_schemas (2.10.1)
41
41
  base64 (0.2.0)
42
42
  bigdecimal (3.1.8)
43
43
  builder (3.2.4)
data/README.md CHANGED
@@ -23,6 +23,27 @@ Or install it yourself as:
23
23
 
24
24
  $ mdtranslator help translate
25
25
 
26
+ ## Development
27
+
28
+ ### Requirements
29
+
30
+ Requires
31
+ - [Ruby](https://www.ruby-lang.org/en/documentation/installation/)
32
+ - bundler (`gem install bundler`)
33
+ - rake (`gem install rake`)
34
+
35
+ ### Tests
36
+
37
+ In order to run the tests, first install the dependencies
38
+
39
+ $ bundle install
40
+
41
+ Then, run the rake command
42
+
43
+ $ bundle exec rake
44
+
45
+ _TODO: There are currently 4 tests that are not passing, related to mdJSON readers and writers_
46
+
26
47
  ## Contributing
27
48
 
28
49
  1. Fork it ( https://github.com/[my-github-username]/mdTranslator/fork )
data/Rakefile CHANGED
@@ -23,6 +23,7 @@ Rake::TestTask.new do |t|
23
23
  'test/writers/iso19115-3/tc*.rb',
24
24
  'test/writers/mdJson/tc*.rb',
25
25
  'test/writers/sbJson/tc*.rb',
26
+ 'test/writers/dcat_us/tc*.rb',
26
27
  'test/translator/tc*.rb'
27
28
  ]
28
29
  t.verbose = true
@@ -34,8 +34,8 @@ Gem::Specification.new do |spec|
34
34
  spec.add_runtime_dependency "thor", "~> 0.19"
35
35
  spec.add_runtime_dependency "uuidtools", "~> 2.1"
36
36
  spec.add_runtime_dependency "json-schema", "~> 2.7"
37
- spec.add_runtime_dependency "adiwg-mdjson_schemas", "2.10.0.pre.beta.5"
38
- spec.add_runtime_dependency "adiwg-mdcodes", "2.10.0"
37
+ spec.add_runtime_dependency "adiwg-mdjson_schemas", "2.10.1"
38
+ spec.add_runtime_dependency "adiwg-mdcodes", "2.10.1"
39
39
  spec.add_runtime_dependency "jbuilder", "~> 2.5"
40
40
  spec.add_runtime_dependency "kramdown", ">= 1.13", "< 3.0"
41
41
  spec.add_runtime_dependency "coderay", "~> 1.1"
@@ -579,6 +579,7 @@ class InternalMetadata
579
579
  # data dictionary ------------------------
580
580
  def newDataDictionary
581
581
  {
582
+ dictionaryId: nil,
582
583
  description: nil,
583
584
  subjects: [],
584
585
  citation: {},
@@ -56,8 +56,10 @@ module ADIWG
56
56
  # data quality 2.1.2.2 (attracce) - Attribute Accuracy Explanation
57
57
  xEvaluationMethod = xQuantitativeAccuracy.xpath('./attracce')
58
58
  unless xEvaluationMethod.empty?
59
- report[:evaluationMethod] = intMetadataClass.newEvaluationMethod
60
- report[:evaluationMethod][:methodDescription] = xEvaluationMethod.text
59
+ evaluationMethod = intMetadataClass.newEvaluationMethod
60
+ evaluationMethod[:name] = 'Attribute Accuracy Explanation'
61
+ evaluationMethod[:methodDescription] = xEvaluationMethod.text
62
+ report[:evaluationMethod] << evaluationMethod
61
63
  end
62
64
  hDataQuality[:report] << report unless report[:quantitativeResult].empty? && report[:evaluationMethod].empty?
63
65
  end
@@ -101,35 +103,29 @@ module ADIWG
101
103
  unless xHorizontalAccuracy.empty?
102
104
  report = intMetadataClass.newDataQualityReport
103
105
  report[:type] = 'DQ_AbsoluteExternalPositionalAccuracy'
104
- # data quality 2.4.1.1 (horizpar) - Horizontal Positional Accuracy Report
106
+ # Combine Horizontal Positional Accuracy Report and Explanation
107
+ descriptive_result_text = ''
105
108
  xHorizontalAccuracyReport = xHorizontalAccuracy.xpath('./horizpar')
106
109
  unless xHorizontalAccuracyReport.empty?
107
- descriptiveResult = intMetadataClass.newDescriptiveResult
108
- descriptiveResult[:name] = 'Horizontal Positional Accuracy Report'
109
- descriptiveResult[:statement] = xHorizontalAccuracyReport.text
110
- report[:descriptiveResult] << descriptiveResult
110
+ descriptive_result_text += xHorizontalAccuracyReport.text
111
111
  end
112
- # data quality 2.4.1.2 (qhorizpa) - Quantitative Horizontal Positional Accuracy Assessment
113
112
  xQuantitativeHorizontalAccuracy = xHorizontalAccuracy.xpath('./qhorizpa')
114
113
  unless xQuantitativeHorizontalAccuracy.empty?
115
- # data quality 2.4.1.2.1 (horizpav) - Horizontal Positional Accuracy Value
116
114
  xHorizontalAccuracyValue = xQuantitativeHorizontalAccuracy.xpath('horizpav')
117
115
  unless xHorizontalAccuracyValue.empty?
118
- quantitativeResult = intMetadataClass.newQuantitativeResult
119
- value = xHorizontalAccuracyValue.text
120
- quantitativeResult[:name] = 'Horizontal Positional Accuracy Value'
121
- quantitativeResult[:values] << value
122
- report[:quantitativeResult] << quantitativeResult
116
+ descriptive_result_text += " Value: #{xHorizontalAccuracyValue.text}"
123
117
  end
124
- # data quality 2.4.1.2.2 (horizpae) - Horizontal Positional Accuracy Explanation
125
118
  xHorizontalAccuracyExplanation = xQuantitativeHorizontalAccuracy.xpath('horizpae')
126
119
  unless xHorizontalAccuracyExplanation.empty?
127
- descriptiveResult = intMetadataClass.newDescriptiveResult
128
- descriptiveResult[:name] = 'Horizontal Positional Accuracy Explanation'
129
- descriptiveResult[:statement] = xHorizontalAccuracyExplanation.text
130
- report[:descriptiveResult] << descriptiveResult
120
+ descriptive_result_text += " Explanation: #{xHorizontalAccuracyExplanation.text}"
131
121
  end
132
122
  end
123
+ unless descriptive_result_text.empty?
124
+ descriptiveResult = intMetadataClass.newDescriptiveResult
125
+ descriptiveResult[:name] = 'Horizontal Positional Accuracy Report'
126
+ descriptiveResult[:statement] = descriptive_result_text
127
+ report[:descriptiveResult] << descriptiveResult
128
+ end
133
129
  hDataQuality[:report] << report
134
130
  end
135
131
  # data quality 2.4.2 (vertacc) - Vertical Positional Accuracy
@@ -137,35 +133,29 @@ module ADIWG
137
133
  unless xVerticalAccuracy.empty?
138
134
  report = intMetadataClass.newDataQualityReport
139
135
  report[:type] = 'DQ_AbsoluteExternalPositionalAccuracy'
140
- # data quality 2.4.2.1 (vertaccr) - Vertical Positional Accuracy Report
136
+ # Combine Vertical Positional Accuracy Report and Explanation
137
+ descriptive_result_text = ''
141
138
  xVerticalAccuracyReport = xVerticalAccuracy.xpath('./vertaccr')
142
139
  unless xVerticalAccuracyReport.empty?
143
- descriptiveResult = intMetadataClass.newDescriptiveResult
144
- descriptiveResult[:name] = 'Vertical Positional Accuracy Report'
145
- descriptiveResult[:statement] = xVerticalAccuracyReport.text
146
- report[:descriptiveResult] << descriptiveResult
140
+ descriptive_result_text += xVerticalAccuracyReport.text
147
141
  end
148
- # data quality 2.4.2.2 (qvertpa) - Quantitative Vertical Positional Accuracy Assessment
149
142
  xVerticalAccuracyAssessment = xVerticalAccuracy.xpath('./qvertpa')
150
143
  unless xVerticalAccuracyAssessment.empty?
151
- # data quality 2.4.2.2.1 (vertaccv) - Vertical Positional Accuracy Value
152
144
  xVerticalAccuracyValue = xVerticalAccuracyAssessment.xpath('vertaccv')
153
145
  unless xVerticalAccuracyValue.empty?
154
- quantitativeResult = intMetadataClass.newQuantitativeResult
155
- value = xVerticalAccuracyValue.text
156
- quantitativeResult[:name] = 'Vertical Positional Accuracy Value'
157
- quantitativeResult[:values] << value
158
- report[:quantitativeResult] << quantitativeResult
146
+ descriptive_result_text += " Value: #{xVerticalAccuracyValue.text}"
159
147
  end
160
- # data quality 2.4.2.2.2 (vertacce) - Vertical Positional Accuracy Explanation
161
148
  xVerticalAccuracyExplanation = xVerticalAccuracyAssessment.xpath('vertacce')
162
149
  unless xVerticalAccuracyExplanation.empty?
163
- descriptiveResult = intMetadataClass.newDescriptiveResult
164
- descriptiveResult[:name] = 'Vertical Positional Accuracy Explanation'
165
- descriptiveResult[:statement] = xVerticalAccuracyExplanation.text
166
- report[:descriptiveResult] << descriptiveResult
150
+ descriptive_result_text += " Explanation: #{xVerticalAccuracyExplanation.text}"
167
151
  end
168
152
  end
153
+ unless descriptive_result_text.empty?
154
+ descriptiveResult = intMetadataClass.newDescriptiveResult
155
+ descriptiveResult[:name] = 'Vertical Positional Accuracy Report'
156
+ descriptiveResult[:statement] = descriptive_result_text
157
+ report[:descriptiveResult] << descriptiveResult
158
+ end
169
159
  hDataQuality[:report] << report
170
160
  end
171
161
  end
@@ -190,4 +180,4 @@ module ADIWG
190
180
  end
191
181
  end
192
182
  end
193
- end
183
+ end
@@ -38,6 +38,14 @@ module ADIWG
38
38
  intMetadataClass = InternalMetadata.new
39
39
  intDictionary = intMetadataClass.newDataDictionary
40
40
 
41
+ # dictionary - id
42
+ if hDictionary.has_key?('dictionaryId')
43
+ s = hDictionary['dictionaryId']
44
+ if s != ''
45
+ intDictionary[:dictionaryId] = s
46
+ end
47
+ end
48
+
41
49
  # dictionary - description
42
50
  if hDictionary.has_key?('description')
43
51
  s = hDictionary['description']
@@ -109,7 +109,7 @@
109
109
  module ADIWG
110
110
  module Mdtranslator
111
111
  # current mdtranslator version
112
- VERSION = "2.21.0-beta.0"
112
+ VERSION = "2.21.0-beta.1"
113
113
  end
114
114
  end
115
115
 
@@ -0,0 +1,98 @@
1
+ require 'jbuilder'
2
+ require_relative 'version'
3
+ require_relative 'sections/dcat_us_dcat_us'
4
+
5
+ module ADIWG
6
+ module Mdtranslator
7
+ module Writers
8
+ module Dcat_us
9
+
10
+ def self.startWriter(intObj, responseObj)
11
+ # set the contact array for use by the writer
12
+ @contacts = intObj[:contacts]
13
+
14
+ # set output flag for null properties
15
+ Jbuilder.ignore_nil(!responseObj[:writerShowTags])
16
+
17
+ # set the format of the output file based on the writer specified
18
+ responseObj[:writerOutputFormat] = 'json'
19
+ responseObj[:writerVersion] = ADIWG::Mdtranslator::Writers::Dcat_us::VERSION
20
+
21
+ # write the dcat_us metadata record
22
+ metadata = Dcat_us.build(intObj, responseObj)
23
+
24
+ # set writer pass to true if no messages
25
+ # false or warning state will be set by writer code
26
+ responseObj[:writerPass] = true if responseObj[:writerMessages].empty?
27
+
28
+ # encode the metadata target as JSON
29
+ metadata.target!
30
+ end
31
+
32
+ # find contact in contact array and return the contact hash
33
+ def self.get_contact_by_index(contactIndex)
34
+ if @contacts[contactIndex]
35
+ return @contacts[contactIndex]
36
+ end
37
+ {}
38
+ end
39
+
40
+ # find contact in contact array and return the contact hash
41
+ def self.get_contact_by_id(contactId)
42
+ @contacts.each do |hContact|
43
+ if hContact[:contactId] == contactId
44
+ return hContact
45
+ end
46
+ end
47
+ {}
48
+ end
49
+
50
+ # find contact in contact array and return the contact index
51
+ def self.get_contact_index_by_id(contactId)
52
+ @contacts.each_with_index do |hContact, index|
53
+ if hContact[:contactId] == contactId
54
+ return index
55
+ end
56
+ end
57
+ {}
58
+ end
59
+
60
+ # ignore jBuilder object mapping when array is empty
61
+ def self.json_map(collection = [], _class)
62
+ if collection.nil? || collection.empty?
63
+ return nil
64
+ else
65
+ collection.map { |item| _class.build(item).attributes! }
66
+ end
67
+ end
68
+
69
+ # find all nested objects in 'obj' that contain the element 'ele'
70
+ def self.nested_objs_by_element(obj, ele, excludeList = [])
71
+ aCollected = []
72
+ obj.each do |key, value|
73
+ skipThisOne = false
74
+ excludeList.each do |exclude|
75
+ if key == exclude.to_sym
76
+ skipThisOne = true
77
+ end
78
+ end
79
+ next if skipThisOne
80
+ if key == ele.to_sym
81
+ aCollected << obj
82
+ elsif obj.is_a?(Array)
83
+ if key.respond_to?(:each)
84
+ aReturn = nested_objs_by_element(key, ele, excludeList)
85
+ aCollected = aCollected.concat(aReturn) unless aReturn.empty?
86
+ end
87
+ elsif obj[key].respond_to?(:each)
88
+ aReturn = nested_objs_by_element(value, ele, excludeList)
89
+ aCollected = aCollected.concat(aReturn) unless aReturn.empty?
90
+ end
91
+ end
92
+ aCollected
93
+ end
94
+
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,10 @@
1
+
2
+ ## dcat_us
3
+
4
+ ### Supported versions
5
+
6
+ > 0.0.x (dcat_us is not currently versioned)
7
+
8
+ ### Writer for Data Catalog Vocabulary (DCAT) v1.1
9
+
10
+
@@ -0,0 +1,55 @@
1
+ require 'jbuilder'
2
+
3
+ module ADIWG
4
+ module Mdtranslator
5
+ module Writers
6
+ module Dcat_us
7
+ module AccessLevel
8
+
9
+ def self.build(intObj)
10
+
11
+ publicArray = ['unclassified', 'unrestricted', 'licenseUnrestricted', 'licenseEndUser']
12
+ nonPublicArray = ['restricted','confidential','secret','topSecret','forOfficialUseOnly','protected','intellectualPropertyRights','restricted','otherRestrictions','private','statutory','confidential','traditionalKnowledge','personallyIdentifiableInformation']
13
+ restrictedPublicArray = ['sensitiveButUnclassified','limitedDistribution','copyright','patent','patentPending','trademark','license','licenseDistributor','in-confidence','threatenedOrEndangered']
14
+
15
+ resourceInfo = intObj[:metadata][:resourceInfo]
16
+ legalConstraints = resourceInfo[:constraints]&.select { |constraint| constraint[:type] == 'legal' }
17
+ securityConstraints = resourceInfo[:constraints]&.select { |constraint| constraint[:type] == 'security' }
18
+
19
+ accessLevelCodes = []
20
+
21
+ # Gather codes from security constraints and legal constraints
22
+ unless securityConstraints.empty?
23
+ securityConstraints.each do |securityConstraint|
24
+ code = securityConstraint[:securityConstraint][:classCode]
25
+ accessLevelCodes << code
26
+ end
27
+ end
28
+ unless legalConstraints.empty?
29
+ legalConstraints.each do |legalConstraint|
30
+ codes = legalConstraint.dig(:legalConstraint, :accessCodes)
31
+ accessLevelCodes.push(*codes)
32
+ end
33
+ end
34
+
35
+ # return access level that is most restrictive
36
+ accessLevelCodes.uniq.each do |code|
37
+ if nonPublicArray.include? code
38
+ return 'non-public'
39
+ end
40
+ end
41
+ accessLevelCodes.uniq.each do |code|
42
+ if restrictedPublicArray.include? code
43
+ return 'restricted public'
44
+ end
45
+ end
46
+
47
+ return 'public'
48
+ end
49
+
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+
@@ -0,0 +1,17 @@
1
+ require 'jbuilder'
2
+
3
+ module ADIWG
4
+ module Mdtranslator
5
+ module Writers
6
+ module Dcat_us
7
+ module AccessURL
8
+
9
+ def self.build(option)
10
+ option[:olResURI] if option[:olResURI].end_with?('.html')
11
+ end
12
+
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,45 @@
1
+ require 'jbuilder'
2
+
3
+ module ADIWG
4
+ module Mdtranslator
5
+ module Writers
6
+ module Dcat_us
7
+ module AccrualPeriodicity
8
+
9
+ def self.build(intObj)
10
+
11
+ frequency_mapping = {
12
+ 'decennial' => 'R/P10Y',
13
+ 'quadrennial' => 'R/P4Y',
14
+ 'annual' => 'R/P1Y',
15
+ 'bimonthly' => 'R/P2M or R/P0.5M',
16
+ 'semiweekly' => 'R/P3.5D',
17
+ 'daily' => 'R/P1D',
18
+ 'biweekly' => 'R/P2W or R/P0.5W',
19
+ 'semiannual' => 'R/P6M',
20
+ 'biennial' => 'R/P2Y',
21
+ 'triennial' => 'R/P3Y',
22
+ 'three times a week' => 'R/P0.33W',
23
+ 'three times a month' => 'R/P0.33M',
24
+ 'continuously updated' => 'R/PT1S',
25
+ 'monthly' => 'R/P1M',
26
+ 'quarterly' => 'R/P3M',
27
+ 'semimonthly' => 'R/P0.5M',
28
+ 'three times a year' => 'R/P4M',
29
+ 'weekly' => 'R/P1W',
30
+ 'hourly' => 'R/PT1H'
31
+ }
32
+
33
+ frequency = intObj[:metadata][:metadataInfo][:metadataMaintenance][:frequency]
34
+
35
+ unless frequency.nil?
36
+ frequency_code = frequency_mapping[frequency.downcase]
37
+ end
38
+ return frequency_code
39
+ end
40
+
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,33 @@
1
+ require 'jbuilder'
2
+
3
+ module ADIWG
4
+ module Mdtranslator
5
+ module Writers
6
+ module Dcat_us
7
+ module BureauCode
8
+
9
+ def self.build(intObj)
10
+
11
+ responsibleParties = intObj[:metadata][:resourceInfo][:citation][:responsibleParties]
12
+ contacts = []
13
+ responsibleParties.each do |party|
14
+ contactId = party[:parties][0][:contactId]
15
+ contacts << Dcat_us.get_contact_by_id(contactId)
16
+ end
17
+
18
+ bureauContacts = contacts&.select { |contact| contact[:externalIdentifier].any? { |id| id[:namespace] == 'bureauCode'} }
19
+
20
+ bureauCodes = []
21
+ bureauContacts.each do |contact|
22
+ bureauCode = contact[:externalIdentifier].find { |id| id[:namespace] == 'bureauCode' }
23
+ bureauCodes << bureauCode[:identifier]
24
+ end
25
+
26
+ return bureauCodes
27
+ end
28
+
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,29 @@
1
+ require 'jbuilder'
2
+
3
+ module ADIWG
4
+ module Mdtranslator
5
+ module Writers
6
+ module Dcat_us
7
+ module ContactPoint
8
+
9
+ def self.build(intObj)
10
+ resourceInfo = intObj[:metadata][:resourceInfo]
11
+ pointOfContact = resourceInfo[:pointOfContacts][0]
12
+ contactId = pointOfContact[:parties][0][:contactId]
13
+
14
+ contact = Dcat_us.get_contact_by_id(contactId)
15
+ fn = contact[:name]
16
+ hasEmail = contact[:eMailList][0]
17
+
18
+ Jbuilder.new do |json|
19
+ json.set!('@type', 'vcard:Contact')
20
+ json.set!('fn', fn)
21
+ json.set!('hasEmail', hasEmail)
22
+ end
23
+
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end