Files
racket-wiki/private/concept-id.rkt
T

49 lines
1.6 KiB
Racket

#lang racket/base
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Canonical concept identity helpers.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(require racket/string
uuid)
(provide concept-id?
normalize-concept-id
new-concept-id
normalized-or-new-concept-id)
(define prefixed-uuid-concept-id-pattern
#px"(?i:^concept-([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$)")
;; Concept ids are stored as plain UUID strings. Validation accepts uppercase
;; input, while normalization always produces the canonical lowercase form.
(define (concept-id? value)
(uuid-string? value))
(define (normalize-concept-id value)
(cond
[(uuid-string? value) (string-downcase value)]
[(and (string? value)
(regexp-match prefixed-uuid-concept-id-pattern value))
=> (lambda (match) (string-downcase (cadr match)))]
[else #f]))
(define (new-concept-id)
(uuid-string))
(define (normalized-or-new-concept-id value)
(or (normalize-concept-id value)
(new-concept-id)))
(module+ test
(require rackunit)
(define sample "a3c4f0d1-22e5-4c42-9a40-cc864993f785")
(check-true (concept-id? sample))
(check-true (concept-id? (string-upcase sample)))
(check-false (concept-id? (string-append "concept-" sample)))
(check-equal? (normalize-concept-id (string-upcase sample)) sample)
(check-equal? (normalize-concept-id (string-append "concept-" sample)) sample)
(check-false (normalize-concept-id "legacy:a:concept-1"))
(check-true (concept-id? (new-concept-id))))