Browse Source

Initial commit: basic config parser.

scossu 2 tháng trước cách đây
commit
b732b58a16

+ 3 - 0
config/model/agent.yml

@@ -0,0 +1,3 @@
+---
+label: Agent
+broader: "pas:Anything"

+ 47 - 0
config/model/anything.yml

@@ -0,0 +1,47 @@
+---
+label: Anything
+description: Superclass of every resource type in the system.
+abstract: true
+
+properties:
+  "pas:id":
+    label: DRS ID
+    type: string
+    min_cardinality: 1
+    max_cardinality: 1
+
+  "pas:refId":
+    label: DRS ID
+    type: string
+    max_cardinality: 1
+
+  "pas:prefLabel":
+    label: Preferred Label
+    type: string
+    max_cardinality: 1
+
+  "pas:altLabel":
+    label: Alternative Label
+    type: string
+
+  "pas:created":
+    label: Created On
+    type: timestamp
+    min_cardinality: 1
+    max_cardinality: 1
+
+  "pas:updated":
+    label: Last Updated On
+    type: timestamp
+    min_cardinality: 1
+    max_cardinality: 1
+
+  "pas:createdBy":
+    label: Created By
+    type: rel
+    range: ["pas:Agent"]
+
+  "pas:updatedBy":
+    label: Last Updated By
+    type: rel
+    range: ["pas:Agent"]

+ 10 - 0
config/model/artifact.yml

@@ -0,0 +1,10 @@
+---
+label: Artifact
+description: Intellectual work.
+broader: "pas:Anything"
+
+properties:
+  "pas:hasFile":
+    label: Has file
+    type: rel
+    range: ["pas:File"]

+ 10 - 0
config/model/file.yml

@@ -0,0 +1,10 @@
+---
+label: File
+broader: "pas:Anything"
+
+properties:
+  "pas:location":
+    label: Location
+    type: string
+    min_cardinality: 1
+    max_cardinality: 1

+ 33 - 0
config/model/part.yml

@@ -0,0 +1,33 @@
+#
+# Part content type: a logical subdivision within an artifact.
+# Resources of this type may be used to build logical structures implemented
+# as linked lists.
+#
+# The `pas:first` property points to the first child in a
+# linked list nested inside the current resource. There may be any number of
+# linked list heads under the same Part, or none.
+#
+# The `pas:next` property points to the next sibling in a linked list. The
+# last item in a list is identified by the lack of this property.
+#
+# In a more complex hierarchy, any given Part may have both "first" and
+# "next" properties.
+
+---
+id: "pas:Part"
+ls_code: Part
+label: Part
+
+broader: "pas:Anything"
+
+properties:
+  "pas:first":
+    label: First child
+    type: resource
+    range: ["pas:Part"]
+
+  "pas:next":
+    label: Next sibling
+    type: resource
+    range: ["pas:Part"]
+    max_cardinality: 1

+ 2 - 0
data/sample_submission/postcard-bag/bagit.txt

@@ -0,0 +1,2 @@
+BagIt-Version: 1.0
+Tag-File-Character-Encoding: UTF-8

BIN
data/sample_submission/postcard-bag/data/12345/12345-back/567890.jpg


BIN
data/sample_submission/postcard-bag/data/12345/12345-front/54321.jpg


+ 17 - 0
data/sample_submission/postcard-bag/data/submission.csv

@@ -0,0 +1,17 @@
+ref,mdkey,mdvalue
+12345,type,Postcard
+,prefLabel,Example Postcard
+,altLabel,This is an alternative label
+,altLabel,And this is another alternative label
+,,Another label only repeating value
+,description,"Note that recto and verso representations have been named front and back, to emphasize that the ordering is not alphabetical."
+
+12345/12345-front,prefLabel,Recto
+,type,Part
+
+12345/12345-front/54321.jpg,type,StillImage
+
+12345/12345-back,prefLabel,Verso
+,type,Part
+
+12345/12345-back/567890.jpg,type,StillImage

+ 3 - 0
data/sample_submission/postcard-bag/manifest-md5.txt

@@ -0,0 +1,3 @@
+6d3e96779489ec928bd54b716ee7b9d3  data/submission.csv
+9db0de0b0c6b40be9cad3828946e8fd0  data/12345/12345-front/54321.jpg
+ccc13ac50e926995da704b51ee4948c0  data/12345/12345-back/567890.jpg

+ 5 - 0
data/sample_submission/postcard-bag/manifest-sha512.txt

@@ -0,0 +1,5 @@
+2b6263572b781ba987778d362969d5e62729fe7cb94694a379ba7af4ea8311d0b5dac499dd0da7a7c5162979ccbf5f943cbb3ee91c2794ab09924969b08ec66c  data/submission.csv
+da8e36bb2fc58834acc535db182b1b1350317a15440e22238a0ba050c2860fb2b4fc2ce7f1c1fa95758d9cdb365913948b7ab26083f1e8325540159b24c6973d  data/DRS_12345/12345-front/54321.TIF
+c6a2dfbafcf8157f76dfca5e65f7bc24e14c52125b8e7b73df0995c9c714bd3f762e4d6692e953bac4aec7ada4ff92ecf5a0317812b036b701843597fb6ac7c6  data/DRS_12345/12345-front/54321.jpg
+ccedf8f20a05a0d34f67965e0858622867bc442a543f3183b7a12c466159805ddd0a3e6484a465344d2c52049ed68312401c62bfa8c14aaeace40cff8a803a4c  data/DRS_12345/12345-back/567890.jpg
+8d663fcd34934399dfb2df28194d9795c97e9c02de4eef709d9b77b572690f04a74a2f88175a35d24e89a08a7839eb2ddb595e0f09804ebe5e523add935ec3db  data/DRS_12345/12345-back/567890.TIF

+ 40 - 0
data/schema.sql

@@ -0,0 +1,40 @@
+/* SQLite schema for pocket_archive. */
+
+CREATE TABLE atbl_art_type (
+    id int PRIMARY KEY AUTOINCREMENT,
+    label text NOT NULL UNIQUE,
+    broader_id int,
+
+    FOREIGN KEY (broader_id) REFERENCES atbl_art_type(id)
+);
+
+/* Metadata schema. Each row represents a field definition. */
+CREATE TABLE atbl_md_schema (
+    id int PRIMARY KEY AUTOINCREMENT,
+    uri TEXT NOT NULL UNIQUE,
+    label TEXT NOT NULL UNIQUE,
+    description TEXT,
+    data_type int NOT NULL,
+    min_card int DEFAULT 0,
+    max_card int,
+    range TEXT
+);
+
+CREATE TABLE tbl_metadatum (
+    id int PRIMARY KEY AUTOINCREMENT,
+    field_id int NOT NULL,
+    value_int int,  /* This includes timestamps. */
+    value_float real,
+    value_str TEXT
+    /* TODO add more types as needs arise. */
+);
+
+CREATE TABLE tbl_artifact (
+    id int PRIMARY KEY AUTOINCREMENT,
+    provided_id TEXT UNIQUE,
+    type_id int NOT NULL,
+    metadata_id int NOT NULL,
+
+    FOREIGN KEY (type_id) REFERENCES atbl_art_type(id),
+    FOREIGN KEY (metadata_id) REFERENCES tbl_metadatum(id) ON DELETE CASCADE
+);

+ 75 - 0
model_parser.lua

@@ -0,0 +1,75 @@
+local string = string
+local table = table
+local io = io
+
+local lyaml = require("lyaml")
+
+
+local M = {}
+
+-- Parameters that do not get inherited.
+local NO_INHERIT = {abstract = true}
+local MODEL_PATH = "./config/model/"
+
+
+local function camel2snake(src)
+    return string.lower(
+        string.gsub(
+            string.gsub (src, "^pas:", ""),  -- Strip namespace.
+            "([^^])(%u)", "%1_%2"  -- Uppercase (except initial) to underscore.
+        )
+    )
+end
+
+
+M.parse_model = function(mod_id)
+    local hierarchy = {}
+
+    local function traverse(mod_id)
+        print("traversing:", mod_id)
+        local fname = camel2snake (mod_id)
+        local fh = assert(io.open(MODEL_PATH .. fname .. ".yml"), "r")
+        local yml_data = fh:read("a")
+        fh:close()
+        local model = lyaml.load(yml_data)
+        model.id = mod_id
+        --print("Model: ")
+        --for k, v in pairs(model) do print (k, v) end
+
+        -- Prepend to hierarchy.
+        table.insert(hierarchy, 1, model)
+
+        if model.broader then traverse(model.broader) end
+    end
+    traverse(mod_id)
+
+    local lineage = {}  -- Config ID lineage, from ancestor to leaf.
+    for _, mod in ipairs(hierarchy) do table.insert(lineage, mod.id) end
+    --[[
+    for k, v in ipairs(hierarchy) do 
+        for kk, vv in pairs(v) do print(k, kk, vv) end
+    end
+    --]]
+
+    local function merge(src, dest)
+        for k, v in pairs(src) do
+            if NO_INHERIT[k] then goto continue end
+            if type(v) == "table" then
+                merge(v, dest[k] or {})
+            else
+                dest[k] = v
+            end
+            ::continue::
+        end
+    end
+    local config = {}
+
+    for _, src_config in ipairs(hierarchy) do
+        print("Merging:", src_config)
+        merge(src_config, config)
+    end
+
+    return config
+end
+
+return M