├── .gitignore ├── LICENSE ├── README.md ├── bin ├── cli.js └── server.js ├── data ├── ISOIEC10646-CJK-JISX0208-1990-compliant.txt ├── ISOIEC10646-CJK-JISX0212-1990-compliant.txt ├── ISOIEC10646-CJK-JISX0213-2004-compliant.txt ├── ISOIEC10646Annex-G-supplement-KATAKANA-compliant.txt ├── ISOIEC10646Annex-G-supplement-NUMERIC-compliant.txt ├── NotUse_ISOIEC10646-CJK-JISX0213-2004-compliant_ALL.txt ├── README.md └── build.js ├── example ├── datamodel.imiv.txt ├── graph.json ├── imicore241.imiv.txt ├── line-delimited.json.txt └── simple.json ├── lib ├── charsets.js └── util.js ├── main.js ├── package-lock.json ├── package.json └── test ├── imicore241.imiv.txt ├── test-charsets.js ├── test-main.js └── test-util.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 IMI Tool Project 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # IMIデータバリデーションコンポーネント 2 | 3 | 所与のデータモデルに対して JSON-LD を検査し、 4 | 場合によってはデータの修正や補完を行いつつ、 5 | 検査結果をメタデータとして追記するライブラリです。 6 | コマンドラインツールおよび WebAPI サーバも提供されます。 7 | 8 | # 利用者向け情報 9 | 10 | 11 | ## インストール 12 | 13 | 適当な作業フォルダを作成しモジュールをインストールします。 14 | 15 | ``` 16 | $ mkdir work 17 | $ cd work 18 | $ npm install IMI-Tool-Project/imi-data-validator 19 | ``` 20 | 21 | ## API 22 | 23 | モジュール imi-data-validator は以下のような API の関数です。 24 | 25 | ``` 26 | module.exports = function(imiv) {..} 27 | ``` 28 | 29 | - imiv: imiv 文字列(必要な語彙定義およびデータモデル定義を連結したもの) 30 | 31 | この関数は関数を生成するジェネレータです。 32 | 生成された関数は以下のような API を持ちます。 33 | 34 | ``` 35 | function(json,options){..} 36 | ``` 37 | 38 | - json: バリデーション対象の JSON 39 | - options: オプションオブジェクト(省略可能、後述) 40 | 41 | 出力はバリデーション結果が付与された JSON です。 42 | 43 | ## 使用例 44 | 45 | 以下の手順では genrate 関数によって imiv から validate 関数が生成され、 46 | validate 関数によって input (JSON) から output (JSON) に変換されます。 47 | 48 | ```main.js 49 | const fs = require('fs'); 50 | const generate = require('imi-data-validator'); 51 | 52 | const imiv = 53 | fs.readFileSync(__dirname+"/node_modules/imi-data-validator/example/imicore241.imiv.txt") + 54 | fs.readFileSync(__dirname+"/node_modules/imi-data-validator/example/datamodel.imiv.txt"); 55 | 56 | const validate = generate(imiv); 57 | 58 | const input = { 59 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 60 | "@type": "法人型", 61 | "表記": "株式会社ほげほげ" 62 | }; 63 | 64 | const output = validate(input); 65 | 66 | console.log(JSON.stringify(output,null,2)); 67 | ``` 68 | 69 | 実行すると以下のような出力が得られます。 70 | 71 | ``` 72 | $ node main.js 73 | { 74 | "@context": [ 75 | "https://imi.go.jp/ns/core/context.jsonld", 76 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 77 | ], 78 | "@type": "法人型", 79 | "表記": "株式会社ほげほげ", 80 | "メタデータ": { 81 | "@type": "hj:更新履歴型", 82 | "hj:更新者": { 83 | "@type": "実体型", 84 | "表記": "IMIデータバリデーションコンポーネント" 85 | }, 86 | "種別": "INFO", 87 | "説明": "このインスタンスはデータモデルに適合しています", 88 | "日時": { 89 | "@type": "日時型", 90 | "標準型日時": "2019-02-13T19:46:14.904+09:00" 91 | } 92 | } 93 | } 94 | $ 95 | ``` 96 | 97 | ### オプション 98 | 99 | generate 関数の第二引数としてオプションを保持したオブジェクトを渡すことができます。 100 | 101 | ``` 102 | const generate = require('imi-data-validator'); 103 | 104 | const imiv = 105 | fs.readFileSync(__dirname+"/example/imicore241.imiv.txt") + 106 | fs.readFileSync(__dirname+"/example/datamodel.imiv.txt"); 107 | 108 | const validate = generate(imiv,{disable_auto_fix:true}); 109 | 110 | ``` 111 | 112 | オプションの意味は以下の通りです。 113 | 114 | #### disable_auto_fix 115 | 116 | このオプションに true が設定された場合にのみデータへの修正・補完が行われず、 ERROR として報告されます。 117 | 118 | それ以外の場合(無指定も含む)はデータへの修正・補完が行われ、WARNING として報告されます。 119 | 120 | 対象となる修正・補完は以下です。 121 | 122 | - インスタンスに省略されたルートクラスをデータモデルから補完 123 | - インスタンスに省略されたルートクラス以外のクラスを、語彙定義から補完 124 | - 文字セット制約(数値)の場合の、全角数字から半角数字への自動変換 125 | - 文字セット制約(カタカナ)の場合の、半角カタカナから全角カタカナへの自動変換 126 | 127 | 128 | ## コマンドラインツールとしての利用 129 | 130 | コマンドラインツールの実体は `bin/cli.js` です。 131 | コマンドラインに語彙定義およびデータモデル定義を指定、 132 | さらに指定されたひとつのファイルまたは標準入力に含まれる JSON をパースして 133 | 変換結果を標準出力に出力します。 134 | 135 | 以下は動作確認用ファイル `example/simple.json` を変換する事例です。 136 | 137 | ``` 138 | $ cd node_modules/imi-data-validator 139 | $ node bin/cli.js example/imicore241.imiv.txt example/datamodel.imiv.txt example/simple.json 140 | { 141 | "@context": [ 142 | "https://imi.go.jp/ns/core/context.jsonld", 143 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 144 | ], 145 | "@type": "法人型", 146 | "表記": "株式会社完全充足", 147 | "組織種別位置": "前", 148 | "組織種別": { 149 | "@type": "コード型", 150 | "識別値": "301", 151 | "表記": "株式会社" 152 | }, 153 | "住所": { 154 | "@type": "住所型", 155 | "表記": "東京都千代田区麹町", 156 | "郵便番号": "1020083", 157 | "都道府県": "東京都", 158 | "市区町村": "千代田区" 159 | }, 160 | "メタデータ": { 161 | "@type": "hj:更新履歴型", 162 | "hj:更新者": { 163 | "@type": "実体型", 164 | "表記": "IMIデータバリデーションコンポーネント" 165 | }, 166 | "種別": "INFO", 167 | "説明": "このインスタンスはデータモデルに適合しています", 168 | "日時": { 169 | "@type": "日時型", 170 | "標準型日時": "2019-02-13T19:50:29.105+09:00" 171 | } 172 | } 173 | } 174 | $ 175 | ``` 176 | 177 | 動作確認用ファイルは以下の3つです。 178 | 179 | - example/simple.json : 単一のインスタンスをもつ JSON-LD 180 | - example/graph.json : 3つのインスタンスをもつ JSON-LD 181 | - example/line-delimited.json.txt : 1行ごとに独立した JSON-LD が記録された Line delimited JSON 182 | 183 | なお、入力形式が Line delimited JSON と判定された場合には、 184 | 出力形式も Line delimited JSON になります。 185 | 186 | ## サーバとしての利用 187 | 188 | コマンドラインツールの実体は `bin/server.js` です。 189 | 以下の手順で任意のポートと語彙・データモデル定義を与えてサーバを起動します。 190 | 191 | ``` 192 | $ cd node_modules/imi-data-validator 193 | $ node bin/server.js 3030 example/imicore241.imiv.txt example/datamodel.imiv.txt 194 | imi-data-validator is running on port 3030 195 | ``` 196 | 197 | なお、ポート番号や語彙・データモデル定義を指定しなかった場合には以下のように使用方法が出力されて終了します。 198 | 199 | ``` 200 | $ node bin/server.js 201 | Usage: node server.js [port number] [IMIV_VOCABULARY]... [IMIV_DATAMODEL] 202 | $ 203 | ``` 204 | 205 | サーバが起動している状態で、 POST メソッドで JSON-LD を送信すると変換結果が出力されます。 206 | 207 | ``` 208 | $ curl -X POST -d '{"@context": "https://imi.go.jp/ns/core/context.jsonld","@type": "法人型","表記": "株式会社ほげほげ"}' localhost:3030 209 | { 210 | "@context": [ 211 | "https://imi.go.jp/ns/core/context.jsonld", 212 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 213 | ], 214 | "@type": "法人型", 215 | "表記": "株式会社ほげほげ", 216 | "メタデータ": { 217 | "@type": "hj:更新履歴型", 218 | "hj:更新者": { 219 | "@type": "実体型", 220 | "表記": "IMIデータバリデーションコンポーネント" 221 | }, 222 | "種別": "INFO", 223 | "説明": "このインスタンスはデータモデルに適合しています", 224 | "日時": { 225 | "@type": "日時型", 226 | "標準型日時": "2019-02-13T19:53:50.648+09:00" 227 | } 228 | } 229 | } 230 | $ 231 | ``` 232 | 233 | # 開発者向け情報 234 | 235 | ## 環境構築 236 | 237 | 以下の手順で環境を構築します。 238 | 239 | ``` 240 | $ git clone https://github.com/IMI-Tool-Project/imi-data-validator.git 241 | $ cd imi-data-validator 242 | $ npm install 243 | ``` 244 | 245 | ## テスト 246 | 247 | 以下の手順でテストが実行され、テスト結果が出力されます。 248 | 249 | ``` 250 | $ npm test 251 | 252 | > imi-data-validator@1.0.0 test imi-data-validator 253 | > mocha 254 | 255 | 256 | 257 | imi-data-validator#charsets 258 | 数字 ISOIEC10646Annex-G-supplement-NUMERIC-compliant 259 | ✓ 定義 260 | ✓ 数字だけの文字列を valid と判定できること 261 | ✓ 数字以外を含む文字列を invalid と判定できること 262 | カタカナ ISOIEC10646Annex-G-supplement-KATAKANA-compliant 263 | ✓ 定義 264 | ✓ カタカナだけの文字列を valid と判定できること 265 | ✓ カタカナ以外を含む文字列を invalid と判定できること 266 | JISX0208 ISOIEC10646-CJK-JISX0208-1990-compliant 267 | ✓ 定義 268 | ✓ JISX0208だけの文字列を valid と判定できること 269 | ✓ JISX0208以外を含む文字列を invalid と判定できること 270 | 271 | (省略) 272 | 273 | $ 274 | ``` 275 | 276 | ## ファイル構成 277 | 278 | 開発対象となる JavaScript は以下の3つです。 279 | 280 | ``` 281 | main.js : 関数本体 282 | lib/util.js : リテラルに対する評価を実施するための関数群 283 | lib/charsets.js : 文字セット URI をキーとして、「文字セット名称」と「文字セット構成要素を正規表現の文字クラス相当に記述した文字列」を格納したオブジェクト 284 | ``` 285 | 286 | なお `lib/charsets.js` は `data/build.js` によって自動生成されます。 287 | 詳しくは `data/README.md` をご覧ください。 288 | -------------------------------------------------------------------------------- /bin/cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const readline = require('readline'); 4 | const generate = require("../main"); 5 | const fs = require("fs"); 6 | 7 | if (process.argv.length < 3) { 8 | console.error("usage: node cli.js [IMIV_VOCABULARY]... [IMIV_DATAMODEL] [JSON]"); 9 | process.exit(1); 10 | } 11 | 12 | let imiv = ""; 13 | let input = null; 14 | for (var i = 2; i < process.argv.length; i++) { 15 | const s = fs.readFileSync(process.argv[i], "UTF-8"); 16 | if (s.match(/^[\s]*{/)) { 17 | if (input === null) 18 | input = fs.createReadStream(process.argv[i], 'UTF-8'); 19 | } else { 20 | imiv += s; 21 | } 22 | } 23 | 24 | const validate = generate(imiv); 25 | 26 | const rl = readline.createInterface({ 27 | input: input || process.stdin, 28 | crlfDelay: Infinity 29 | }); 30 | 31 | let mode = 0; 32 | 33 | const lines = []; 34 | 35 | rl.on('line', (line) => { 36 | if (mode === 0) { 37 | try { 38 | JSON.parse(line); 39 | mode = 2; 40 | } catch (e) { 41 | mode = 1; 42 | } 43 | 44 | } 45 | switch (mode) { 46 | case 1: 47 | lines.push(line); 48 | break; 49 | case 2: 50 | try { 51 | const json = JSON.parse(line); 52 | const done = validate(json); 53 | console.log(JSON.stringify(done)); 54 | } catch (e) { 55 | console.log(`# error ${e.toString()}`) 56 | } 57 | break; 58 | } 59 | }).on('close', () => { 60 | if (mode === 1) { 61 | try { 62 | const json = JSON.parse(lines.join("\n")); 63 | const done = validate(json); 64 | console.log(JSON.stringify(done, null, 2)); 65 | } catch (e) { 66 | console.log(`# error ${e.toString()}`) 67 | } 68 | } 69 | }); 70 | -------------------------------------------------------------------------------- /bin/server.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const generate = require("../main"); 4 | const http = require("http"); 5 | const fs = require("fs"); 6 | 7 | if (process.argv.length < 4 || !process.argv[2].match(/^[1-9][0-9]*$/)) { 8 | console.error("Usage: node server.js [port number] [IMIV_VOCABULARY]... [IMIV_DATAMODEL]"); 9 | process.exit(1); 10 | } 11 | 12 | const port = parseInt(process.argv[2]); 13 | 14 | let imiv = ""; 15 | for (var i = 3; i < process.argv.length; i++) { 16 | imiv += fs.readFileSync(process.argv[i], "UTF-8"); 17 | } 18 | 19 | const validate = generate(imiv); 20 | 21 | 22 | const server = http.createServer((req, res) => { 23 | if (req.method !== "POST") { 24 | res.writeHead(405, { 25 | "Content-Type": "text/plain", 26 | "Allow": "POST" 27 | }); 28 | res.write([ 29 | "405 Method Not Allowed, only POST method is supported", 30 | "" 31 | ].join("\n")); 32 | res.end(); 33 | return; 34 | } 35 | 36 | new Promise(resolve => { 37 | let data = ""; 38 | req.on("data", (chunk) => { 39 | data += chunk; 40 | }).on("end", () => { 41 | resolve(data); 42 | }); 43 | }).then(data => { 44 | let json = null; 45 | try { 46 | json = JSON.parse(data); 47 | } catch (e) { 48 | res.writeHead(400, { 49 | "Content-Type": "text/plain" 50 | }); 51 | res.write([ 52 | "400 Bad Request, exception occurred during parsing POST body as JSON", 53 | "", 54 | e.toString(), 55 | "" 56 | ].join("\n")); 57 | res.end(); 58 | return; 59 | } 60 | try { 61 | const done = validate(json); 62 | res.writeHead(200, { 63 | "Content-Type": "application/json" 64 | }); 65 | res.write([ 66 | JSON.stringify(done, null, 2), 67 | "" 68 | ].join("\n")); 69 | res.end(); 70 | } catch (e) { 71 | res.writeHead(500, { 72 | "Content-Type": "text/plain" 73 | }); 74 | res.write([ 75 | "500 Internal Server Error", 76 | "", 77 | e.toString(), 78 | "" 79 | ].join("\n")); 80 | res.end(); 81 | return; 82 | } 83 | }); 84 | 85 | }); 86 | server.listen(port); 87 | 88 | console.log(`imi-data-validator is running on port ${port}`); 89 | -------------------------------------------------------------------------------- /data/ISOIEC10646-CJK-JISX0213-2004-compliant.txt: -------------------------------------------------------------------------------- 1 | # 2 | # @文字セット定義管理情報 3 | # 参照 URI: "https://imi.go.jp/CommonCharacterSets/ISOIEC10646-CJK-JISX0213-2004-compliant" 4 | # 名称: "IMI ユーティリティ文字セット-漢字(JISX0213)" 5 | # 説明: "本文字セット定義は、平成30年度経済産業省デジタルプラットフォーム構築事業(IMI情報共有基盤推進事業)で使用する目的で作成したものであり、IMI情報共有基盤として提供するものではありません。" 6 | # 作成者: "名称: '独立行政法人情報処理推進機構'@ja, 'IPA'@en |URL: 'https://www.ipa.go.jp/'" 7 | # 公開日付: "2019-02-04" 8 | # 9 | # @出典情報 10 | # 文書名: "ISO/IEC 10646" 11 | # 版: "第 5 版" 12 | # 説明: "Kanji J source: kIRG_Jsource - J3,J3A,J13A,J13,JA3,J4,A14,JA4" 13 | # 参照部分: "23.2 Source references file for CJK Ideographs" 14 | # 発行元: "名称: 'ISO/IEC JTC1'|URL: 'https://www.iso.org/isoiec-jtc-1.html'" 15 | # 発行日付: "2017-12" 16 | # 17 | # @出典情報 18 | # 文書名: "7ビット及び8ビットの2バイト情報交換用符号化拡張漢字集合" 19 | # 版: "JIS X 0213:2000" 20 | # 説明: "JIS X 0208に規定する漢字を除く、第三水準、第四水準" 21 | # 参照部分: "付属書6 漢字の分類及び配列" 22 | # 発行元: "名称: '日本規格協会'|URL: 'https://www.jsa.or.jp/'" 23 | # 発行日付: "2000" 24 | # 25 | 26 | # 含まれる文字の定義 27 | 3402 28 | 3406 29 | 342C 30 | 342E 31 | 3468 32 | 346A 33 | 3492 34 | 34B5 35 | 34BC 36 | 34C1 37 | 34C7 38 | 34DB 39 | 351F 40 | 355D 41 | 355E 42 | 3563 43 | 356E 44 | 35A6 45 | 35A8 46 | 35C5 47 | 35DA 48 | 35F4 49 | 3605 50 | 364A 51 | 3691 52 | 3696 53 | 3699 54 | 36CF 55 | 3761 56 | 3762 57 | 376B 58 | 376C 59 | 3775 60 | 378D 61 | 37C1 62 | 37E2 63 | 37E8 64 | 37F4 65 | 37FD 66 | 3800 67 | 382F 68 | 3836 69 | 3840 70 | 385C 71 | 3861 72 | 38FA 73 | 3917 74 | 391A 75 | 396F 76 | 3A6E 77 | 3A73 78 | 3AD6 79 | 3AD7 80 | 3AEA 81 | 3B0E 82 | 3B1A 83 | 3B1C 84 | 3B22 85 | 3B6D 86 | 3B77 87 | 3B87 88 | 3B88 89 | 3B8D 90 | 3BA4 91 | 3BB6 92 | 3BC3 93 | 3BCD 94 | 3BF0 95 | 3C0F 96 | 3C26 97 | 3CC3 98 | 3CD2 99 | 3D11 100 | 3D1E 101 | 3D64 102 | 3D9A 103 | 3DC0 104 | 3DD4 105 | 3E05 106 | 3E3F 107 | 3E60 108 | 3E66 109 | 3E68 110 | 3E83 111 | 3E94 112 | 3F57 113 | 3F72 114 | 3F75 115 | 3F77 116 | 3FAE 117 | 3FC9 118 | 3FD7 119 | 4039 120 | 4058 121 | 4093 122 | 4105 123 | 4148 124 | 414F 125 | 4163 126 | 41B4 127 | 41BF 128 | 41E6 129 | 41EE 130 | 41F3 131 | 4207 132 | 420E 133 | 4264 134 | 42C6 135 | 42D6 136 | 42DD 137 | 4302 138 | 432B 139 | 4343 140 | 43EE 141 | 43F0 142 | 4408 143 | 4417 144 | 441C 145 | 4422 146 | 4453 147 | 445B 148 | 4476 149 | 447A 150 | 4491 151 | 44B3 152 | 44BE 153 | 44D4 154 | 4508 155 | 450D 156 | 4525 157 | 4543 158 | 459D 159 | 45B8 160 | 45E5 161 | 45EA 162 | 460F 163 | 4641 164 | 4665 165 | 46A1 166 | 46AF 167 | 470C 168 | 4764 169 | 47FD 170 | 4816 171 | 4844 172 | 484E 173 | 48B5 174 | 49B0 175 | 49E7 176 | 49FA 177 | 4A04 178 | 4A29 179 | 4ABC 180 | 4B3B 181 | 4BC2 182 | 4BCA 183 | 4BD2 184 | 4BE8 185 | 4C17 186 | 4C20 187 | 4CC4 188 | 4CD1 189 | 4D07 190 | 4D77 191 | 4E02 192 | 4E0F 193 | 4E12 194 | 4E28 195 | 4E29 196 | 4E2B 197 | 4E2C 198 | 4E2E 199 | 4E2F 200 | 4E30 201 | 4E40 202 | 4E47 203 | 4E48 204 | 4E51 205 | 4E5A 206 | 4E69 207 | 4E8D 208 | 4E9D 209 | 4EB9 210 | 4EBB 211 | 4EBC 212 | 4EC3 213 | 4EC8 214 | 4ED0 215 | 4EDA 216 | 4EE1 217 | 4EEB 218 | 4EF1 219 | 4EF5 220 | 4EFD 221 | 4EFF 222 | 4F00 223 | 4F03 224 | 4F0B 225 | 4F16 226 | 4F37 227 | 4F3E 228 | 4F48 229 | 4F49 230 | 4F54 231 | 4F56 232 | 4F58 233 | 4F5F 234 | 4F60 235 | 4F64 236 | 4F6A 237 | 4F6C 238 | 4F77 239 | 4F78 240 | 4F7A 241 | 4F7D 242 | 4F7E 243 | 4F82 244 | 4F85 245 | 4F8A 246 | 4F92 247 | 4F94 248 | 4F97 249 | 4F9A 250 | 4FB2 251 | 4FBE 252 | 4FC5 253 | 4FC9 254 | 4FCB 255 | 4FCF 256 | 4FD2 257 | 4FE0 258 | 4FE6 259 | 4FF1 260 | 4FF2 261 | 5000 262 | 5001 263 | 5002 264 | 500E 265 | 5010 266 | 5013 267 | 5018 268 | 501C 269 | 501E 270 | 5022 271 | 5027 272 | 502E 273 | 503B 274 | 5040 275 | 5041 276 | 5042 277 | 5046 278 | 504E 279 | 5053 280 | 5057 281 | 5063 282 | 5066 283 | 506A 284 | 5070 285 | 5088 286 | 5092 287 | 5093 288 | 5094 289 | 5095 290 | 5096 291 | 509C 292 | 50A3 293 | 50AA 294 | 50B1 295 | 50BA 296 | 50BB 297 | 50C4 298 | 50C7 299 | 50CC 300 | 50CE 301 | 50D0 302 | 50D4 303 | 50D9 304 | 50E1 305 | 50E6 306 | 50E9 307 | 50F2 308 | 50F3 309 | 5103 310 | 5106 311 | 5108 312 | 510B 313 | 5117 314 | 511B 315 | 511E 316 | 5135 317 | 514A 318 | 5155 319 | 5157 320 | 5160 321 | 5173 322 | 517B 323 | 5183 324 | 518B 325 | 5198 326 | 519D 327 | 51A3 328 | 51AD 329 | 51BC 330 | 51C3 331 | 51CA 332 | 51DE 333 | 51E2 334 | 51EE 335 | 51F3 336 | 51F4 337 | 5201 338 | 5202 339 | 5212 340 | 5213 341 | 5215 342 | 5216 343 | 5249 344 | 5255 345 | 5257 346 | 525C 347 | 525D 348 | 5261 349 | 526C 350 | 5277 351 | 5282 352 | 5284 353 | 5293 354 | 5298 355 | 52A4 356 | 52A6 357 | 52AF 358 | 52BA 359 | 52BB 360 | 52C8 361 | 52CA 362 | 52CC 363 | 52D0 364 | 52D1 365 | 52D6 366 | 52DB 367 | 52F0 368 | 52F7 369 | 52FB 370 | 5300 371 | 5307 372 | 530A 373 | 530B 374 | 531C 375 | 5324 376 | 5335 377 | 533E 378 | 5342 379 | 5361 380 | 5363 381 | 5367 382 | 536C 383 | 537A 384 | 537D 385 | 5393 386 | 539D 387 | 53A4 388 | 53B2 389 | 53B4 390 | 53B7 391 | 53C0 392 | 53D5 393 | 53DA 394 | 53F4 395 | 53F5 396 | 5412 397 | 541E 398 | 5424 399 | 5427 400 | 5428 401 | 5443 402 | 544D 403 | 5455 404 | 5462 405 | 5466 406 | 546B 407 | 546C 408 | 5474 409 | 547F 410 | 5488 411 | 548A 412 | 548D 413 | 5495 414 | 5496 415 | 549C 416 | 54A0 417 | 54A1 418 | 54A6 419 | 54A9 420 | 54AD 421 | 54AE 422 | 54B7 423 | 54BA 424 | 54BF 425 | 54C3 426 | 54C6 427 | 54EC 428 | 54EF 429 | 54F1 430 | 54F3 431 | 54FF 432 | 5500 433 | 5501 434 | 5509 435 | 550E 436 | 552B 437 | 5535 438 | 553C 439 | 5541 440 | 5547 441 | 554A 442 | 5550 443 | 555E 444 | 5560 445 | 5561 446 | 5564 447 | 557D 448 | 5581 449 | 5582 450 | 5586 451 | 5588 452 | 558E 453 | 5591 454 | 55AD 455 | 55BF 456 | 55C9 457 | 55CC 458 | 55CE 459 | 55D1 460 | 55D2 461 | 55DD 462 | 55E2 463 | 55E9 464 | 5607 465 | 5608 466 | 560E 467 | 5610 468 | 5628 469 | 5630 470 | 5637 471 | 563B 472 | 563D 473 | 563F 474 | 5640 475 | 5647 476 | 5649 477 | 5653 478 | 565E 479 | 5660 480 | 5666 481 | 566D 482 | 566F 483 | 5671 484 | 5672 485 | 5676 486 | 5688 487 | 568C 488 | 5695 489 | 5699 490 | 569A 491 | 569D 492 | 569E 493 | 56A8 494 | 56A9 495 | 56AC 496 | 56AD 497 | 56B2 498 | 56B3 499 | 56C5 500 | 56C9 501 | 56CA 502 | 56CD 503 | 56DF 504 | 56E8 505 | 56F6 506 | 56F7 507 | 570A 508 | 5715 509 | 5721 510 | 5723 511 | 5729 512 | 572F 513 | 5733 514 | 5734 515 | 5745 516 | 5746 517 | 574C 518 | 574D 519 | 5768 520 | 576F 521 | 5770 522 | 5773 523 | 5774 524 | 5775 525 | 5777 526 | 577B 527 | 577C 528 | 579A 529 | 579C 530 | 579D 531 | 579E 532 | 57A8 533 | 57AC 534 | 57B8 535 | 57C7 536 | 57C8 537 | 57CC 538 | 57CF 539 | 57D7 540 | 57DE 541 | 57E4 542 | 57E6 543 | 57ED 544 | 57F0 545 | 57F5 546 | 57F6 547 | 57F8 548 | 57FB 549 | 57FD 550 | 57FF 551 | 5804 552 | 5809 553 | 581E 554 | 5820 555 | 5827 556 | 5832 557 | 5839 558 | 5849 559 | 584C 560 | 5861 561 | 5864 562 | 5867 563 | 587C 564 | 5889 565 | 588A 566 | 588B 567 | 588D 568 | 588F 569 | 5890 570 | 5894 571 | 589D 572 | 589E 573 | 58A9 574 | 58AA 575 | 58B1 576 | 58C3 577 | 58CD 578 | 58CE 579 | 58D2 580 | 58D4 581 | 58DA 582 | 58E0 583 | 58E2 584 | 58E9 585 | 58F3 586 | 58F4 587 | 5905 588 | 5906 589 | 590B 590 | 590C 591 | 590D 592 | 5914 593 | 5924 594 | 593D 595 | 5946 596 | 595B 597 | 595D 598 | 595F 599 | 596D 600 | 5975 601 | 5976 602 | 597C 603 | 598B 604 | 5992 605 | 599F 606 | 59A4 607 | 59AE 608 | 59BC 609 | 59C3 610 | 59C8 611 | 59CD 612 | 59D2 613 | 59DD 614 | 59DE 615 | 59E3 616 | 59E4 617 | 59E7 618 | 59EE 619 | 59F8 620 | 5A0C 621 | 5A0D 622 | 5A13 623 | 5A17 624 | 5A23 625 | 5A27 626 | 5A2D 627 | 5A55 628 | 5A65 629 | 5A67 630 | 5A6D 631 | 5A77 632 | 5A7A 633 | 5A7E 634 | 5A84 635 | 5A8B 636 | 5A9C 637 | 5A9E 638 | 5A9F 639 | 5AA0 640 | 5AA2 641 | 5AA7 642 | 5AB1 643 | 5AB3 644 | 5AB5 645 | 5ABA 646 | 5ABF 647 | 5AC4 648 | 5ADA 649 | 5ADC 650 | 5AE0 651 | 5AE5 652 | 5AEE 653 | 5AF0 654 | 5AF5 655 | 5B00 656 | 5B08 657 | 5B17 658 | 5B19 659 | 5B25 660 | 5B2D 661 | 5B34 662 | 5B41 663 | 5B4C 664 | 5B52 665 | 5B56 666 | 5B68 667 | 5B6F 668 | 5B7C 669 | 5B7D 670 | 5B7F 671 | 5B81 672 | 5B84 673 | 5B93 674 | 5B96 675 | 5BAC 676 | 5BC0 677 | 5BCE 678 | 5BD6 679 | 5BD8 680 | 5BEC 681 | 5BF1 682 | 5BFD 683 | 5C03 684 | 5C12 685 | 5C1E 686 | 5C23 687 | 5C29 688 | 5C2B 689 | 5C30 690 | 5C5B 691 | 5C5F 692 | 5C62 693 | 5C63 694 | 5C67 695 | 5C68 696 | 5C69 697 | 5C70 698 | 5C7A 699 | 5C7C 700 | 5C88 701 | 5C8A 702 | 5C8F 703 | 5C9F 704 | 5CA0 705 | 5CA2 706 | 5CA3 707 | 5CA6 708 | 5CA7 709 | 5CAA 710 | 5CAD 711 | 5CB5 712 | 5CBA 713 | 5CC9 714 | 5CCB 715 | 5CD0 716 | 5CD2 717 | 5CF4 718 | 5D06 719 | 5D0D 720 | 5D10 721 | 5D1D 722 | 5D20 723 | 5D24 724 | 5D26 725 | 5D27 726 | 5D2B 727 | 5D31 728 | 5D39 729 | 5D42 730 | 5D46 731 | 5D47 732 | 5D4A 733 | 5D53 734 | 5D61 735 | 5D6A 736 | 5D6D 737 | 5D70 738 | 5D81 739 | 5D88 740 | 5D92 741 | 5D94 742 | 5D97 743 | 5D99 744 | 5DA0 745 | 5DA4 746 | 5DA7 747 | 5DB0 748 | 5DB2 749 | 5DB4 750 | 5DB8 751 | 5DB9 752 | 5DCB 753 | 5DD1 754 | 5DD7 755 | 5DD8 756 | 5DE0 757 | 5DE2 758 | 5DE4 759 | 5DE9 760 | 5E00 761 | 5E12 762 | 5E14 763 | 5E15 764 | 5E18 765 | 5E1F 766 | 5E2E 767 | 5E3E 768 | 5E49 769 | 5E56 770 | 5E58 771 | 5E5E 772 | 5E6B 773 | 5E6C 774 | 5E6D 775 | 5E6E 776 | 5E77 777 | 5EA5 778 | 5EAA 779 | 5EAC 780 | 5EB9 781 | 5EBE 782 | 5EBF 783 | 5EC6 784 | 5ECB 785 | 5ED2 786 | 5ED9 787 | 5EF9 788 | 5EFD 789 | 5F00 790 | 5F02 791 | 5F07 792 | 5F08 793 | 5F0E 794 | 5F1C 795 | 5F1D 796 | 5F1E 797 | 5F23 798 | 5F34 799 | 5F36 800 | 5F3D 801 | 5F40 802 | 5F45 803 | 5F47 804 | 5F54 805 | 5F58 806 | 5F63 807 | 5F64 808 | 5F67 809 | 5F72 810 | 5F7D 811 | 5F7E 812 | 5F89 813 | 5F8F 814 | 5F9C 815 | 5FA2 816 | 5FA4 817 | 5FA7 818 | 5FAF 819 | 5FB5 820 | 5FB7 821 | 5FB8 822 | 5FC4 823 | 5FC7 824 | 5FC9 825 | 5FCB 826 | 5FD2 827 | 5FD3 828 | 5FD4 829 | 5FDE 830 | 5FE1 831 | 5FE2 832 | 5FE9 833 | 5FEE 834 | 5FEF 835 | 5FF3 836 | 5FFC 837 | 600D 838 | 6014 839 | 6017 840 | 6018 841 | 6022 842 | 6024 843 | 6033 844 | 6035 845 | 6047 846 | 604C 847 | 607F 848 | 608A 849 | 6095 850 | 609D 851 | 609E 852 | 60A8 853 | 60B0 854 | 60B1 855 | 60BE 856 | 60C8 857 | 60CB 858 | 60D4 859 | 60D5 860 | 60D9 861 | 60DB 862 | 60DD 863 | 60EE 864 | 60F2 865 | 60F5 866 | 60F8 867 | 6110 868 | 6112 869 | 6113 870 | 6119 871 | 611C 872 | 611E 873 | 612B 874 | 6130 875 | 6137 876 | 613A 877 | 6141 878 | 6146 879 | 6160 880 | 617C 881 | 618D 882 | 6192 883 | 6193 884 | 6197 885 | 6198 886 | 61A5 887 | 61A8 888 | 61AD 889 | 61B9 890 | 61BC 891 | 61D5 892 | 61DD 893 | 61DF 894 | 61F5 895 | 6215 896 | 6222 897 | 6223 898 | 6229 899 | 623E 900 | 6243 901 | 6246 902 | 624C 903 | 6251 904 | 6252 905 | 6256 906 | 625A 907 | 6261 908 | 6264 909 | 626D 910 | 626F 911 | 6273 912 | 627B 913 | 6285 914 | 6299 915 | 62A6 916 | 62C4 917 | 62D5 918 | 62D6 919 | 62FC 920 | 62FD 921 | 6303 922 | 630A 923 | 630D 924 | 6310 925 | 6318 926 | 6332 927 | 6335 928 | 6339 929 | 633B 930 | 633C 931 | 6341 932 | 6343 933 | 6344 934 | 634E 935 | 6359 936 | 6365 937 | 636C 938 | 637C 939 | 6384 940 | 6394 941 | 6399 942 | 63BD 943 | 63D4 944 | 63D5 945 | 63DC 946 | 63E0 947 | 63E5 948 | 63EB 949 | 63EC 950 | 63ED 951 | 63F2 952 | 63F5 953 | 63F7 954 | 6409 955 | 6410 956 | 6414 957 | 641E 958 | 6422 959 | 6425 960 | 6429 961 | 642F 962 | 6451 963 | 645A 964 | 645B 965 | 645D 966 | 6460 967 | 646D 968 | 6473 969 | 6479 970 | 647D 971 | 6487 972 | 6491 973 | 649D 974 | 649F 975 | 64BE 976 | 64BF 977 | 64C4 978 | 64CA 979 | 64CB 980 | 64CC 981 | 64CE 982 | 64D0 983 | 64D5 984 | 64D7 985 | 64E4 986 | 64E5 987 | 64F7 988 | 64FB 989 | 64FF 990 | 6504 991 | 650F 992 | 6514 993 | 6516 994 | 651E 995 | 6522 996 | 6529 997 | 6532 998 | 6544 999 | 6554 1000 | 6567 1001 | 656B 1002 | 657A 1003 | 6581 1004 | 6584 1005 | 6585 1006 | 658A 1007 | 659D 1008 | 65B2 1009 | 65B5 1010 | 65B8 1011 | 65BF 1012 | 65C2 1013 | 65C9 1014 | 65D4 1015 | 65F2 1016 | 65F9 1017 | 65FC 1018 | 6600 1019 | 6604 1020 | 6608 1021 | 6609 1022 | 6615 1023 | 661E 1024 | 6621 1025 | 6622 1026 | 6624 1027 | 662A 1028 | 662B 1029 | 6630 1030 | 6631 1031 | 6633 1032 | 663A 1033 | 6645 1034 | 6648 1035 | 664C 1036 | 664E 1037 | 6651 1038 | 6657 1039 | 6659 1040 | 665A 1041 | 665B 1042 | 6661 1043 | 6663 1044 | 6665 1045 | 666A 1046 | 666B 1047 | 666C 1048 | 666D 1049 | 6673 1050 | 6677 1051 | 6678 1052 | 667B 1053 | 6680 1054 | 668D 1055 | 6690 1056 | 6692 1057 | 6699 1058 | 66A0 1059 | 66AD 1060 | 66B1 1061 | 66B2 1062 | 66B5 1063 | 66BB 1064 | 66BF 1065 | 66C6 1066 | 66C8 1067 | 66DB 1068 | 66E8 1069 | 66EC 1070 | 66FA 1071 | 66FB 1072 | 6701 1073 | 6705 1074 | 6712 1075 | 6713 1076 | 6719 1077 | 6733 1078 | 6747 1079 | 6748 1080 | 674C 1081 | 674D 1082 | 6754 1083 | 675D 1084 | 6766 1085 | 6774 1086 | 6776 1087 | 677B 1088 | 6781 1089 | 6792 1090 | 6793 1091 | 6798 1092 | 679B 1093 | 67B0 1094 | 67B2 1095 | 67BB 1096 | 67C0 1097 | 67C3 1098 | 67C8 1099 | 67D2 1100 | 67D7 1101 | 67D9 1102 | 67DB 1103 | 67F0 1104 | 67F7 1105 | 67F9 1106 | 67FC 1107 | 6801 1108 | 6810 1109 | 6818 1110 | 681D 1111 | 681F 1112 | 682C 1113 | 682D 1114 | 6831 1115 | 6833 1116 | 683B 1117 | 683E 1118 | 6844 1119 | 6845 1120 | 6849 1121 | 684C 1122 | 6852 1123 | 6855 1124 | 6857 1125 | 685B 1126 | 686B 1127 | 686E 1128 | 6872 1129 | 6875 1130 | 687A 1131 | 687C 1132 | 6882 1133 | 6890 1134 | 6896 1135 | 6898 1136 | 6899 1137 | 689A 1138 | 689C 1139 | 68A3 1140 | 68A5 1141 | 68AA 1142 | 68AB 1143 | 68B2 1144 | 68B4 1145 | 68BB 1146 | 68C3 1147 | 68C5 1148 | 68C8 1149 | 68CC 1150 | 68CF 1151 | 68D0 1152 | 68D6 1153 | 68D9 1154 | 68E4 1155 | 68E5 1156 | 68E8 1157 | 68EC 1158 | 68ED 1159 | 68F0 1160 | 68F1 1161 | 68F7 1162 | 68FB 1163 | 68FC 1164 | 6903 1165 | 6907 1166 | 690A 1167 | 6935 1168 | 693B 1169 | 6942 1170 | 6946 1171 | 6949 1172 | 6957 1173 | 6963 1174 | 6964 1175 | 6968 1176 | 6969 1177 | 696C 1178 | 6972 1179 | 697A 1180 | 697F 1181 | 6980 1182 | 6992 1183 | 6996 1184 | 6998 1185 | 69A5 1186 | 69A6 1187 | 69AD 1188 | 69B0 1189 | 69B7 1190 | 69BA 1191 | 69BC 1192 | 69C0 1193 | 69CF 1194 | 69D1 1195 | 69D6 1196 | 69E2 1197 | 69E3 1198 | 69E9 1199 | 69EA 1200 | 69EE 1201 | 69EF 1202 | 69F3 1203 | 69F4 1204 | 69F5 1205 | 69F6 1206 | 69FE 1207 | 6A0F 1208 | 6A11 1209 | 6A15 1210 | 6A1A 1211 | 6A1D 1212 | 6A30 1213 | 6A32 1214 | 6A33 1215 | 6A34 1216 | 6A3B 1217 | 6A3E 1218 | 6A3F 1219 | 6A45 1220 | 6A46 1221 | 6A49 1222 | 6A4E 1223 | 6A50 1224 | 6A52 1225 | 6A56 1226 | 6A5B 1227 | 6A64 1228 | 6A6B 1229 | 6A73 1230 | 6A7A 1231 | 6A7E 1232 | 6A83 1233 | 6A89 1234 | 6A8B 1235 | 6A91 1236 | 6A94 1237 | 6A9D 1238 | 6A9E 1239 | 6A9F 1240 | 6AA1 1241 | 6AA5 1242 | 6AAB 1243 | 6ABD 1244 | 6AC6 1245 | 6AD0 1246 | 6AD4 1247 | 6ADC 1248 | 6ADD 1249 | 6AE4 1250 | 6AE7 1251 | 6AEC 1252 | 6AF1 1253 | 6AF2 1254 | 6AF3 1255 | 6AFD 1256 | 6B0B 1257 | 6B0F 1258 | 6B10 1259 | 6B11 1260 | 6B17 1261 | 6B1B 1262 | 6B1E 1263 | 6B2C 1264 | 6B2F 1265 | 6B35 1266 | 6B46 1267 | 6B4A 1268 | 6B56 1269 | 6B58 1270 | 6B60 1271 | 6B65 1272 | 6B67 1273 | 6B6C 1274 | 6B75 1275 | 6B77 1276 | 6B7A 1277 | 6B81 1278 | 6B82 1279 | 6B9B 1280 | 6BA9 1281 | 6BAD 1282 | 6BAE 1283 | 6BBD 1284 | 6BBE 1285 | 6BC7 1286 | 6BC8 1287 | 6BC9 1288 | 6BCF 1289 | 6BD6 1290 | 6BD7 1291 | 6BDA 1292 | 6BE6 1293 | 6BE7 1294 | 6BEE 1295 | 6BF1 1296 | 6BFF 1297 | 6C02 1298 | 6C05 1299 | 6C0A 1300 | 6C0E 1301 | 6C10 1302 | 6C33 1303 | 6C35 1304 | 6C36 1305 | 6C3A 1306 | 6C3F 1307 | 6C4D 1308 | 6C59 1309 | 6C5B 1310 | 6C5C 1311 | 6C67 1312 | 6C6D 1313 | 6C74 1314 | 6C76 1315 | 6C84 1316 | 6C85 1317 | 6C86 1318 | 6C89 1319 | 6C94 1320 | 6C95 1321 | 6C97 1322 | 6C98 1323 | 6C9C 1324 | 6CAA 1325 | 6CAD 1326 | 6CC2 1327 | 6CC6 1328 | 6CD0 1329 | 6CD4 1330 | 6CD6 1331 | 6CDA 1332 | 6CDC 1333 | 6CE0 1334 | 6CE9 1335 | 6CEB 1336 | 6CEC 1337 | 6CED 1338 | 6CEE 1339 | 6CFB 1340 | 6D00 1341 | 6D04 1342 | 6D0A 1343 | 6D0E 1344 | 6D24 1345 | 6D26 1346 | 6D27 1347 | 6D2E 1348 | 6D2F 1349 | 6D31 1350 | 6D34 1351 | 6D39 1352 | 6D3C 1353 | 6D3F 1354 | 6D58 1355 | 6D5B 1356 | 6D5E 1357 | 6D60 1358 | 6D65 1359 | 6D70 1360 | 6D80 1361 | 6D81 1362 | 6D82 1363 | 6D87 1364 | 6D89 1365 | 6D8A 1366 | 6D8D 1367 | 6D91 1368 | 6D94 1369 | 6D98 1370 | 6DAA 1371 | 6DAB 1372 | 6DAC 1373 | 6DAE 1374 | 6DB4 1375 | 6DBF 1376 | 6DC2 1377 | 6DC4 1378 | 6DC8 1379 | 6DCE 1380 | 6DCF 1381 | 6DD0 1382 | 6DD6 1383 | 6DDA 1384 | 6DDB 1385 | 6DDD 1386 | 6DDF 1387 | 6DE9 1388 | 6DF6 1389 | 6DFC 1390 | 6E17 1391 | 6E1E 1392 | 6E22 1393 | 6E27 1394 | 6E32 1395 | 6E34 1396 | 6E36 1397 | 6E3C 1398 | 6E44 1399 | 6E48 1400 | 6E49 1401 | 6E4B 1402 | 6E4C 1403 | 6E4F 1404 | 6E51 1405 | 6E53 1406 | 6E54 1407 | 6E57 1408 | 6E5C 1409 | 6E5E 1410 | 6E63 1411 | 6E93 1412 | 6EA7 1413 | 6EAB 1414 | 6EB1 1415 | 6EB4 1416 | 6EBF 1417 | 6EC1 1418 | 6EC3 1419 | 6EC7 1420 | 6ECA 1421 | 6ECE 1422 | 6ED9 1423 | 6EEB 1424 | 6EF9 1425 | 6EFB 1426 | 6F0A 1427 | 6F0C 1428 | 6F10 1429 | 6F18 1430 | 6F1A 1431 | 6F25 1432 | 6F2A 1433 | 6F2F 1434 | 6F33 1435 | 6F35 1436 | 6F36 1437 | 6F3C 1438 | 6F51 1439 | 6F52 1440 | 6F57 1441 | 6F59 1442 | 6F5A 1443 | 6F5E 1444 | 6F60 1445 | 6F61 1446 | 6F62 1447 | 6F68 1448 | 6F7D 1449 | 6F7E 1450 | 6F88 1451 | 6F8C 1452 | 6F8D 1453 | 6F90 1454 | 6F94 1455 | 6F96 1456 | 6F98 1457 | 6F9F 1458 | 6FA0 1459 | 6FA5 1460 | 6FA7 1461 | 6FAF 1462 | 6FB5 1463 | 6FB6 1464 | 6FBC 1465 | 6FBE 1466 | 6FC7 1467 | 6FC8 1468 | 6FC9 1469 | 6FCA 1470 | 6FDA 1471 | 6FDE 1472 | 6FE9 1473 | 6FF0 1474 | 6FF5 1475 | 6FF9 1476 | 6FFC 1477 | 7000 1478 | 7005 1479 | 7006 1480 | 7007 1481 | 700A 1482 | 7023 1483 | 7028 1484 | 7039 1485 | 703A 1486 | 703C 1487 | 7043 1488 | 7047 1489 | 704A 1490 | 704B 1491 | 704E 1492 | 7054 1493 | 705D 1494 | 705E 1495 | 7064 1496 | 7065 1497 | 7069 1498 | 706C 1499 | 706E 1500 | 7075 1501 | 7076 1502 | 707E 1503 | 7081 1504 | 7085 1505 | 7086 1506 | 7095 1507 | 7097 1508 | 709F 1509 | 70A4 1510 | 70AB 1511 | 70B1 1512 | 70B7 1513 | 70BB 1514 | 70CA 1515 | 70D1 1516 | 70D3 1517 | 70D4 1518 | 70D8 1519 | 70DC 1520 | 70E4 1521 | 70EC 1522 | 7103 1523 | 7104 1524 | 7106 1525 | 7107 1526 | 7108 1527 | 710C 1528 | 710F 1529 | 711E 1530 | 7120 1531 | 712B 1532 | 712E 1533 | 712F 1534 | 7130 1535 | 7131 1536 | 7146 1537 | 7147 1538 | 714A 1539 | 7150 1540 | 7151 1541 | 7152 1542 | 7153 1543 | 715C 1544 | 715E 1545 | 7160 1546 | 7168 1547 | 7180 1548 | 7185 1549 | 7187 1550 | 7192 1551 | 7196 1552 | 719B 1553 | 71A0 1554 | 71A2 1555 | 71AE 1556 | 71AF 1557 | 71B3 1558 | 71BA 1559 | 71C1 1560 | 71C4 1561 | 71CB 1562 | 71D3 1563 | 71D9 1564 | 71DC 1565 | 71FE 1566 | 7200 1567 | 7207 1568 | 7215 1569 | 722B 1570 | 7234 1571 | 7238 1572 | 7239 1573 | 7242 1574 | 7253 1575 | 7255 1576 | 7256 1577 | 7257 1578 | 7263 1579 | 726E 1580 | 726F 1581 | 7278 1582 | 727F 1583 | 728D 1584 | 728E 1585 | 729B 1586 | 72AD 1587 | 72AE 1588 | 72B0 1589 | 72B1 1590 | 72BE 1591 | 72C0 1592 | 72C1 1593 | 72CC 1594 | 72F3 1595 | 72FA 1596 | 72FB 1597 | 7307 1598 | 7312 1599 | 7318 1600 | 7319 1601 | 7327 1602 | 7328 1603 | 732C 1604 | 7331 1605 | 7333 1606 | 7339 1607 | 733D 1608 | 7350 1609 | 7352 1610 | 7366 1611 | 736B 1612 | 736C 1613 | 736E 1614 | 736F 1615 | 7371 1616 | 7377 1617 | 737C 1618 | 7381 1619 | 7385 1620 | 738A 1621 | 7394 1622 | 7395 1623 | 7398 1624 | 739C 1625 | 739E 1626 | 739F 1627 | 73A0 1628 | 73A2 1629 | 73A5 1630 | 73A6 1631 | 73A8 1632 | 73AB 1633 | 73B5 1634 | 73B7 1635 | 73B9 1636 | 73BC 1637 | 73BF 1638 | 73C5 1639 | 73C9 1640 | 73CB 1641 | 73CF 1642 | 73D6 1643 | 73D9 1644 | 73E1 1645 | 73E3 1646 | 73E7 1647 | 73E9 1648 | 73F9 1649 | 73FA 1650 | 7401 1651 | 7407 1652 | 740A 1653 | 7413 1654 | 741A 1655 | 741B 1656 | 7424 1657 | 7426 1658 | 7428 1659 | 742A 1660 | 742B 1661 | 742C 1662 | 742E 1663 | 742F 1664 | 7430 1665 | 7431 1666 | 7439 1667 | 7440 1668 | 7443 1669 | 7444 1670 | 7446 1671 | 7447 1672 | 744B 1673 | 744D 1674 | 7452 1675 | 7453 1676 | 7457 1677 | 745D 1678 | 7462 1679 | 746B 1680 | 746D 1681 | 7471 1682 | 7481 1683 | 7485 1684 | 7486 1685 | 7487 1686 | 7488 1687 | 7489 1688 | 7490 1689 | 7492 1690 | 7497 1691 | 7498 1692 | 7499 1693 | 749C 1694 | 749F 1695 | 74A0 1696 | 74A1 1697 | 74A3 1698 | 74A5 1699 | 74A6 1700 | 74A8 1701 | 74A9 1702 | 74AA 1703 | 74AB 1704 | 74B5 1705 | 74B9 1706 | 74BA 1707 | 74BB 1708 | 74BF 1709 | 74C8 1710 | 74C9 1711 | 74D6 1712 | 74D8 1713 | 74DA 1714 | 74DE 1715 | 74EB 1716 | 74EF 1717 | 74FA 1718 | 74FF 1719 | 7501 1720 | 7517 1721 | 7520 1722 | 7524 1723 | 752A 1724 | 752F 1725 | 753D 1726 | 753E 1727 | 7540 1728 | 7548 1729 | 754E 1730 | 7550 1731 | 7552 1732 | 756C 1733 | 756F 1734 | 7571 1735 | 7572 1736 | 7579 1737 | 757A 1738 | 757D 1739 | 757E 1740 | 7581 1741 | 758C 1742 | 7592 1743 | 75A2 1744 | 75B0 1745 | 75B7 1746 | 75BF 1747 | 75C0 1748 | 75C6 1749 | 75CE 1750 | 75CF 1751 | 75D3 1752 | 75DD 1753 | 75DF 1754 | 75E0 1755 | 75E4 1756 | 75E7 1757 | 75EC 1758 | 75EE 1759 | 75F1 1760 | 75F9 1761 | 7600 1762 | 7602 1763 | 7603 1764 | 7607 1765 | 7608 1766 | 760F 1767 | 7613 1768 | 7615 1769 | 7616 1770 | 7618 1771 | 7619 1772 | 761B 1773 | 761C 1774 | 761E 1775 | 7625 1776 | 7626 1777 | 7628 1778 | 762D 1779 | 7633 1780 | 7635 1781 | 763C 1782 | 7641 1783 | 7643 1784 | 7649 1785 | 764B 1786 | 7655 1787 | 7664 1788 | 7665 1789 | 766D 1790 | 766E 1791 | 766F 1792 | 7671 1793 | 7681 1794 | 7695 1795 | 769B 1796 | 769C 1797 | 769D 1798 | 769E 1799 | 76A0 1800 | 76A1 1801 | 76A6 1802 | 76A7 1803 | 76A8 1804 | 76AA 1805 | 76AF 1806 | 76B6 1807 | 76C5 1808 | 76C9 1809 | 76CC 1810 | 76CE 1811 | 76D4 1812 | 76E6 1813 | 76E8 1814 | 76EC 1815 | 76F1 1816 | 76FC 1817 | 770A 1818 | 7717 1819 | 7719 1820 | 771A 1821 | 772D 1822 | 7734 1823 | 7735 1824 | 7736 1825 | 7746 1826 | 774D 1827 | 774E 1828 | 7758 1829 | 775C 1830 | 775F 1831 | 7760 1832 | 7762 1833 | 776A 1834 | 7772 1835 | 777A 1836 | 777C 1837 | 777D 1838 | 7780 1839 | 7794 1840 | 779A 1841 | 779F 1842 | 77A2 1843 | 77A4 1844 | 77A9 1845 | 77AA 1846 | 77DE 1847 | 77DF 1848 | 77E0 1849 | 77E4 1850 | 77E6 1851 | 77EA 1852 | 77EC 1853 | 77F0 1854 | 77F4 1855 | 77FB 1856 | 7805 1857 | 7806 1858 | 7809 1859 | 780D 1860 | 7819 1861 | 7821 1862 | 782C 1863 | 782D 1864 | 7843 1865 | 7847 1866 | 784E 1867 | 784F 1868 | 7851 1869 | 7864 1870 | 7868 1871 | 786A 1872 | 786E 1873 | 788A 1874 | 7894 1875 | 789D 1876 | 789E 1877 | 789F 1878 | 78A4 1879 | 78AD 1880 | 78B0 1881 | 78BB 1882 | 78C8 1883 | 78CC 1884 | 78CE 1885 | 78D5 1886 | 78E0 1887 | 78E1 1888 | 78E4 1889 | 78E6 1890 | 78F2 1891 | 78F7 1892 | 78F9 1893 | 78FA 1894 | 78FB 1895 | 78FE 1896 | 7900 1897 | 7910 1898 | 791B 1899 | 791C 1900 | 7925 1901 | 792E 1902 | 7930 1903 | 7931 1904 | 7934 1905 | 793B 1906 | 7945 1907 | 7946 1908 | 794A 1909 | 7958 1910 | 795B 1911 | 795C 1912 | 7967 1913 | 7972 1914 | 7979 1915 | 7994 1916 | 7995 1917 | 7996 1918 | 7998 1919 | 799B 1920 | 79A1 1921 | 79A9 1922 | 79B1 1923 | 79B4 1924 | 79B8 1925 | 79BB 1926 | 79C2 1927 | 79C7 1928 | 79C8 1929 | 79CA 1930 | 79CC 1931 | 79CD 1932 | 79D4 1933 | 79D6 1934 | 79DE 1935 | 79EB 1936 | 79ED 1937 | 7A03 1938 | 7A0A 1939 | 7A11 1940 | 7A15 1941 | 7A1B 1942 | 7A1E 1943 | 7A2D 1944 | 7A38 1945 | 7A39 1946 | 7A47 1947 | 7A4C 1948 | 7A56 1949 | 7A59 1950 | 7A5C 1951 | 7A5D 1952 | 7A5F 1953 | 7A60 1954 | 7A67 1955 | 7A6A 1956 | 7A6D 1957 | 7A75 1958 | 7A78 1959 | 7A82 1960 | 7A85 1961 | 7A8A 1962 | 7A90 1963 | 7AA0 1964 | 7AA3 1965 | 7AAC 1966 | 7AB3 1967 | 7AB9 1968 | 7ABB 1969 | 7ABC 1970 | 7ABE 1971 | 7ACC 1972 | 7ACE 1973 | 7AD1 1974 | 7AE7 1975 | 7AE8 1976 | 7AEB 1977 | 7AF4 1978 | 7AFD 1979 | 7B07 1980 | 7B12 1981 | 7B27 1982 | 7B2A 1983 | 7B2D 1984 | 7B2E 1985 | 7B2F 1986 | 7B31 1987 | 7B3B 1988 | 7B3D 1989 | 7B41 1990 | 7B47 1991 | 7B4E 1992 | 7B55 1993 | 7B60 1994 | 7B64 1995 | 7B66 1996 | 7B69 1997 | 7B6D 1998 | 7B6F 1999 | 7B72 2000 | 7B73 2001 | 7B79 2002 | 7B7F 2003 | 7B90 2004 | 7B91 2005 | 7B9B 2006 | 7B9E 2007 | 7BAF 2008 | 7BB5 2009 | 7BBC 2010 | 7BC5 2011 | 7BCA 2012 | 7BD4 2013 | 7BD6 2014 | 7BD7 2015 | 7BD9 2016 | 7BDA 2017 | 7BEA 2018 | 7BF0 2019 | 7C01 2020 | 7C03 2021 | 7C0B 2022 | 7C0E 2023 | 7C0F 2024 | 7C1E 2025 | 7C20 2026 | 7C26 2027 | 7C31 2028 | 7C33 2029 | 7C36 2030 | 7C45 2031 | 7C4A 2032 | 7C51 2033 | 7C57 2034 | 7C59 2035 | 7C5E 2036 | 7C61 2037 | 7C69 2038 | 7C6D 2039 | 7C6E 2040 | 7C6F 2041 | 7C70 2042 | 7C79 2043 | 7C8F 2044 | 7C94 2045 | 7CA0 2046 | 7CA6 2047 | 7CB6 2048 | 7CB7 2049 | 7CBC 2050 | 7CBF 2051 | 7CC4 2052 | 7CC8 2053 | 7CCD 2054 | 7CD5 2055 | 7CD7 2056 | 7CD9 2057 | 7CDD 2058 | 7CE6 2059 | 7CEB 2060 | 7CF5 2061 | 7D03 2062 | 7D07 2063 | 7D08 2064 | 7D09 2065 | 7D12 2066 | 7D13 2067 | 7D1D 2068 | 7D1E 2069 | 7D23 2070 | 7D31 2071 | 7D3D 2072 | 7D3E 2073 | 7D40 2074 | 7D41 2075 | 7D47 2076 | 7D48 2077 | 7D53 2078 | 7D59 2079 | 7D5A 2080 | 7D5C 2081 | 7D6A 2082 | 7D70 2083 | 7D7A 2084 | 7D7F 2085 | 7D83 2086 | 7D86 2087 | 7D88 2088 | 7D8B 2089 | 7D8C 2090 | 7D97 2091 | 7D9D 2092 | 7DA0 2093 | 7DA6 2094 | 7DA7 2095 | 7DAA 2096 | 7DB6 2097 | 7DB7 2098 | 7DC0 2099 | 7DC2 2100 | 7DCC 2101 | 7DD6 2102 | 7DD7 2103 | 7DD9 2104 | 7DE3 2105 | 7DE6 2106 | 7DF1 2107 | 7DF9 2108 | 7E08 2109 | 7E10 2110 | 7E11 2111 | 7E15 2112 | 7E17 2113 | 7E1D 2114 | 7E20 2115 | 7E27 2116 | 7E28 2117 | 7E2C 2118 | 7E45 2119 | 7E47 2120 | 7E52 2121 | 7E61 2122 | 7E6B 2123 | 7E73 2124 | 7E75 2125 | 7E7E 2126 | 7E86 2127 | 7E87 2128 | 7E8A 2129 | 7E8D 2130 | 7E91 2131 | 7E98 2132 | 7E9A 2133 | 7F3B 2134 | 7F3C 2135 | 7F3E 2136 | 7F43 2137 | 7F44 2138 | 7F47 2139 | 7F4F 2140 | 7F52 2141 | 7F61 2142 | 7F63 2143 | 7F64 2144 | 7F6D 2145 | 7F7D 2146 | 7F7E 2147 | 7F90 2148 | 7F91 2149 | 7F96 2150 | 7F97 2151 | 7F9C 2152 | 7FAD 2153 | 7FBF 2154 | 7FC3 2155 | 7FCE 2156 | 7FCF 2157 | 7FDB 2158 | 7FDF 2159 | 7FE3 2160 | 7FE5 2161 | 7FEC 2162 | 7FEE 2163 | 7FEF 2164 | 7FF2 2165 | 7FFA 2166 | 8002 2167 | 8008 2168 | 800A 2169 | 800E 2170 | 8011 2171 | 8014 2172 | 8016 2173 | 8024 2174 | 8026 2175 | 802C 2176 | 8030 2177 | 8035 2178 | 8037 2179 | 803C 2180 | 8043 2181 | 8066 2182 | 8071 2183 | 8075 2184 | 807B 2185 | 8099 2186 | 809C 2187 | 80A4 2188 | 80A7 2189 | 80B8 2190 | 80C5 2191 | 80CA 2192 | 80D5 2193 | 80D7 2194 | 80D8 2195 | 80E0 2196 | 80E6 2197 | 80F3 2198 | 80F5 2199 | 80FB 2200 | 810D 2201 | 8116 2202 | 8118 2203 | 811E 2204 | 8124 2205 | 8127 2206 | 812C 2207 | 8135 2208 | 813D 2209 | 814A 2210 | 8160 2211 | 8167 2212 | 8168 2213 | 8169 2214 | 816D 2215 | 8181 2216 | 8184 2217 | 8185 2218 | 8198 2219 | 81B2 2220 | 81BB 2221 | 81C1 2222 | 81C3 2223 | 81CA 2224 | 81CF 2225 | 81D6 2226 | 81D7 2227 | 81DB 2228 | 81E4 2229 | 81EC 2230 | 81FD 2231 | 81FF 2232 | 8204 2233 | 8219 2234 | 8221 2235 | 8222 2236 | 8232 2237 | 8234 2238 | 823C 2239 | 8245 2240 | 8246 2241 | 8249 2242 | 824B 2243 | 824F 2244 | 8257 2245 | 825C 2246 | 8260 2247 | 8263 2248 | 8274 2249 | 8279 2250 | 827D 2251 | 827F 2252 | 8283 2253 | 828A 2254 | 828E 2255 | 8293 2256 | 82A1 2257 | 82A3 2258 | 82A4 2259 | 82A7 2260 | 82A8 2261 | 82A9 2262 | 82AE 2263 | 82B2 2264 | 82B4 2265 | 82B7 2266 | 82BA 2267 | 82BC 2268 | 82BE 2269 | 82BF 2270 | 82C6 2271 | 82D5 2272 | 82E2 2273 | 82E8 2274 | 82F7 2275 | 82FD 2276 | 82FE 2277 | 8300 2278 | 8301 2279 | 8307 2280 | 8308 2281 | 830C 2282 | 831B 2283 | 831D 2284 | 8322 2285 | 832D 2286 | 8330 2287 | 833A 2288 | 833C 2289 | 8343 2290 | 8344 2291 | 8347 2292 | 8351 2293 | 8354 2294 | 8355 2295 | 8357 2296 | 8362 2297 | 8363 2298 | 837D 2299 | 837F 2300 | 8386 2301 | 838D 2302 | 8392 2303 | 8394 2304 | 8395 2305 | 8398 2306 | 839B 2307 | 839D 2308 | 83A7 2309 | 83A9 2310 | 83BF 2311 | 83C0 2312 | 83C7 2313 | 83C9 2314 | 83CF 2315 | 83D0 2316 | 83D1 2317 | 83D4 2318 | 83DD 2319 | 83E1 2320 | 83E5 2321 | 83EA 2322 | 83F9 2323 | 8401 2324 | 8406 2325 | 840A 2326 | 840F 2327 | 8411 2328 | 8415 2329 | 8417 2330 | 8439 2331 | 8448 2332 | 844A 2333 | 844F 2334 | 8451 2335 | 8452 2336 | 8459 2337 | 845A 2338 | 845C 2339 | 845F 2340 | 8465 2341 | 8470 2342 | 8473 2343 | 8476 2344 | 8478 2345 | 847C 2346 | 8481 2347 | 8485 2348 | 8497 2349 | 849E 2350 | 84A6 2351 | 84AF 2352 | 84B4 2353 | 84BA 2354 | 84BE 2355 | 84C0 2356 | 84C2 2357 | 84CE 2358 | 84CF 2359 | 84D3 2360 | 84DC 2361 | 84E7 2362 | 84EA 2363 | 84EF 2364 | 84F0 2365 | 84F1 2366 | 84FA 2367 | 84FD 2368 | 850C 2369 | 851B 2370 | 851E 2371 | 8523 2372 | 8524 2373 | 8525 2374 | 852B 2375 | 852F 2376 | 8532 2377 | 8534 2378 | 853E 2379 | 854F 2380 | 8551 2381 | 8553 2382 | 8559 2383 | 855E 2384 | 8561 2385 | 8562 2386 | 8564 2387 | 856F 2388 | 857A 2389 | 857B 2390 | 857D 2391 | 857F 2392 | 8581 2393 | 8586 2394 | 858C 2395 | 858F 2396 | 8593 2397 | 859D 2398 | 859F 2399 | 85A2 2400 | 85AD 2401 | 85B0 2402 | 85B7 2403 | 85BC 2404 | 85C7 2405 | 85CA 2406 | 85CB 2407 | 85CE 2408 | 85D8 2409 | 85D9 2410 | 85DF 2411 | 85E1 2412 | 85E6 2413 | 85ED 2414 | 85F6 2415 | 85FF 2416 | 8600 2417 | 8604 2418 | 8605 2419 | 8610 2420 | 8611 2421 | 8612 2422 | 8618 2423 | 861E 2424 | 8621 2425 | 8624 2426 | 8627 2427 | 8629 2428 | 8638 2429 | 8639 2430 | 863C 2431 | 8640 2432 | 8641 2433 | 8653 2434 | 8656 2435 | 8657 2436 | 865B 2437 | 8662 2438 | 866C 2439 | 866F 2440 | 8675 2441 | 8677 2442 | 867A 2443 | 8687 2444 | 8689 2445 | 868D 2446 | 8691 2447 | 8698 2448 | 869C 2449 | 869D 2450 | 86A8 2451 | 86B1 2452 | 86B3 2453 | 86B8 2454 | 86C1 2455 | 86C3 2456 | 86D1 2457 | 86D5 2458 | 86D7 2459 | 86E3 2460 | 86E6 2461 | 86FA 2462 | 86FC 2463 | 86FD 2464 | 8705 2465 | 8707 2466 | 870B 2467 | 870E 2468 | 8710 2469 | 8713 2470 | 8719 2471 | 871F 2472 | 8721 2473 | 8723 2474 | 8731 2475 | 873A 2476 | 873E 2477 | 8740 2478 | 8743 2479 | 8751 2480 | 8758 2481 | 8764 2482 | 8765 2483 | 8771 2484 | 8772 2485 | 877C 2486 | 8787 2487 | 8788 2488 | 8789 2489 | 878B 2490 | 8793 2491 | 87A0 2492 | 87A7 2493 | 87AC 2494 | 87AD 2495 | 87B5 2496 | 87BE 2497 | 87C1 2498 | 87CE 2499 | 87D6 2500 | 87DF 2501 | 87E3 2502 | 87E5 2503 | 87E6 2504 | 87EA 2505 | 87EB 2506 | 87EC 2507 | 87ED 2508 | 87F5 2509 | 8801 2510 | 8803 2511 | 8806 2512 | 880A 2513 | 880B 2514 | 8810 2515 | 8813 2516 | 8814 2517 | 881F 2518 | 8828 2519 | 882E 2520 | 8832 2521 | 883C 2522 | 884A 2523 | 8858 2524 | 885F 2525 | 8864 2526 | 8869 2527 | 886F 2528 | 8898 2529 | 88A0 2530 | 88AA 2531 | 88BC 2532 | 88BD 2533 | 88BE 2534 | 88C0 2535 | 88CA 2536 | 88CE 2537 | 88D1 2538 | 88D2 2539 | 88D3 2540 | 88DB 2541 | 88F0 2542 | 88F1 2543 | 88F5 2544 | 8901 2545 | 8918 2546 | 8919 2547 | 891A 2548 | 891C 2549 | 8927 2550 | 8930 2551 | 8932 2552 | 8937 2553 | 8939 2554 | 8940 2555 | 8942 2556 | 8945 2557 | 8949 2558 | 8962 2559 | 8980 2560 | 8989 2561 | 8990 2562 | 8994 2563 | 899F 2564 | 89B0 2565 | 89B7 2566 | 89D4 2567 | 89D6 2568 | 89D8 2569 | 89E5 2570 | 89EB 2571 | 89F1 2572 | 89F3 2573 | 89F6 2574 | 89FD 2575 | 89FF 2576 | 8A11 2577 | 8A12 2578 | 8A14 2579 | 8A15 2580 | 8A21 2581 | 8A22 2582 | 8A35 2583 | 8A37 2584 | 8A3E 2585 | 8A45 2586 | 8A47 2587 | 8A4D 2588 | 8A4E 2589 | 8A58 2590 | 8A5D 2591 | 8A61 2592 | 8A75 2593 | 8A79 2594 | 8A90 2595 | 8AA7 2596 | 8AAE 2597 | 8AB7 2598 | 8ABE 2599 | 8AD0 2600 | 8AD7 2601 | 8ADF 2602 | 8AF4 2603 | 8AF6 2604 | 8AFC 2605 | 8B05 2606 | 8B0A 2607 | 8B0D 2608 | 8B1C 2609 | 8B1F 2610 | 8B2D 2611 | 8B43 2612 | 8B46 2613 | 8B51 2614 | 8B54 2615 | 8B59 2616 | 8B5E 2617 | 8B69 2618 | 8B76 2619 | 8B7F 2620 | 8B81 2621 | 8B8B 2622 | 8B94 2623 | 8B95 2624 | 8B9C 2625 | 8B9D 2626 | 8B9E 2627 | 8C39 2628 | 8C3D 2629 | 8C45 2630 | 8C47 2631 | 8C49 2632 | 8C4F 2633 | 8C54 2634 | 8C57 2635 | 8C68 2636 | 8C69 2637 | 8C6D 2638 | 8C73 2639 | 8C92 2640 | 8C93 2641 | 8C99 2642 | 8C9B 2643 | 8CA4 2644 | 8CD5 2645 | 8CD6 2646 | 8CD9 2647 | 8CE1 2648 | 8CF0 2649 | 8CF1 2650 | 8CF4 2651 | 8CF8 2652 | 8CFE 2653 | 8D09 2654 | 8D0E 2655 | 8D12 2656 | 8D1B 2657 | 8D6C 2658 | 8D84 2659 | 8D95 2660 | 8DA6 2661 | 8DAF 2662 | 8DC6 2663 | 8DC8 2664 | 8DCE 2665 | 8DD1 2666 | 8DD7 2667 | 8DD9 2668 | 8DEC 2669 | 8DFD 2670 | 8E06 2671 | 8E0C 2672 | 8E14 2673 | 8E16 2674 | 8E20 2675 | 8E21 2676 | 8E22 2677 | 8E23 2678 | 8E27 2679 | 8E36 2680 | 8E39 2681 | 8E3D 2682 | 8E4B 2683 | 8E54 2684 | 8E62 2685 | 8E6C 2686 | 8E6D 2687 | 8E6F 2688 | 8E70 2689 | 8E7B 2690 | 8E98 2691 | 8E9E 2692 | 8EAE 2693 | 8EB3 2694 | 8EB5 2695 | 8EB6 2696 | 8EBB 2697 | 8EC0 2698 | 8ED1 2699 | 8ED4 2700 | 8EF9 2701 | 8EFA 2702 | 8F00 2703 | 8F08 2704 | 8F17 2705 | 8F1E 2706 | 8F2B 2707 | 8F2D 2708 | 8F36 2709 | 8F40 2710 | 8F4A 2711 | 8F54 2712 | 8F58 2713 | 8FA4 2714 | 8FA6 2715 | 8FB4 2716 | 8FB5 2717 | 8FB6 2718 | 8FC1 2719 | 8FC6 2720 | 8FCA 2721 | 8FCD 2722 | 8FD3 2723 | 8FD5 2724 | 8FE0 2725 | 8FE4 2726 | 8FE8 2727 | 8FEE 2728 | 8FF1 2729 | 8FF5 2730 | 8FFB 2731 | 9002 2732 | 9008 2733 | 900C 2734 | 902D 2735 | 9037 2736 | 9043 2737 | 9044 2738 | 905D 2739 | 9085 2740 | 9088 2741 | 908C 2742 | 9090 2743 | 9095 2744 | 9097 2745 | 9099 2746 | 909B 2747 | 90A1 2748 | 90A2 2749 | 90B0 2750 | 90B3 2751 | 90B6 2752 | 90BE 2753 | 90C3 2754 | 90C4 2755 | 90C5 2756 | 90C7 2757 | 90C8 2758 | 90D7 2759 | 90DC 2760 | 90DD 2761 | 90DE 2762 | 90DF 2763 | 90EB 2764 | 90EF 2765 | 90F2 2766 | 90F4 2767 | 90F6 2768 | 90FE 2769 | 90FF 2770 | 9100 2771 | 9104 2772 | 9106 2773 | 9114 2774 | 9115 2775 | 9116 2776 | 9118 2777 | 911C 2778 | 911E 2779 | 9122 2780 | 9123 2781 | 9127 2782 | 912F 2783 | 9131 2784 | 9134 2785 | 9137 2786 | 9139 2787 | 913A 2788 | 913D 2789 | 9146 2790 | 9147 2791 | 9148 2792 | 9157 2793 | 9159 2794 | 915B 2795 | 9161 2796 | 9164 2797 | 9174 2798 | 9179 2799 | 9183 2800 | 9185 2801 | 918E 2802 | 919E 2803 | 91A8 2804 | 91AC 2805 | 91AE 2806 | 91B1 2807 | 91B3 2808 | 91B6 2809 | 91BC 2810 | 91C3 2811 | 91C4 2812 | 91D7 2813 | 91DA 2814 | 91E4 2815 | 91E5 2816 | 91EC 2817 | 91ED 2818 | 91EE 2819 | 91F1 2820 | 91FB 2821 | 9201 2822 | 9207 2823 | 920A 2824 | 9210 2825 | 9216 2826 | 9217 2827 | 9233 2828 | 9238 2829 | 9239 2830 | 923A 2831 | 923C 2832 | 9240 2833 | 9242 2834 | 9243 2835 | 9247 2836 | 924A 2837 | 924E 2838 | 924F 2839 | 9251 2840 | 9256 2841 | 9259 2842 | 9260 2843 | 9261 2844 | 9265 2845 | 9267 2846 | 9268 2847 | 9278 2848 | 927C 2849 | 927D 2850 | 927F 2851 | 9288 2852 | 9289 2853 | 928D 2854 | 9297 2855 | 9299 2856 | 929F 2857 | 92A7 2858 | 92AB 2859 | 92B2 2860 | 92BF 2861 | 92C0 2862 | 92C2 2863 | 92C6 2864 | 92CB 2865 | 92CC 2866 | 92CE 2867 | 92D0 2868 | 92D3 2869 | 92D7 2870 | 92D9 2871 | 92E0 2872 | 92E5 2873 | 92E7 2874 | 92F7 2875 | 92F9 2876 | 92FB 2877 | 92FF 2878 | 9302 2879 | 9304 2880 | 930D 2881 | 9311 2882 | 9315 2883 | 931D 2884 | 931E 2885 | 931F 2886 | 9321 2887 | 9325 2888 | 9327 2889 | 9329 2890 | 9347 2891 | 9348 2892 | 9349 2893 | 934A 2894 | 9351 2895 | 9357 2896 | 935A 2897 | 9364 2898 | 9365 2899 | 936A 2900 | 936B 2901 | 9370 2902 | 9371 2903 | 9373 2904 | 9388 2905 | 938B 2906 | 938F 2907 | 939B 2908 | 939E 2909 | 93A1 2910 | 93A3 2911 | 93BA 2912 | 93C1 2913 | 93C6 2914 | 93C7 2915 | 93DC 2916 | 93DE 2917 | 93DF 2918 | 93E2 2919 | 93E7 2920 | 93F1 2921 | 93F5 2922 | 93FB 2923 | 93FD 2924 | 9404 2925 | 9409 2926 | 940F 2927 | 9416 2928 | 9417 2929 | 9432 2930 | 9433 2931 | 9434 2932 | 943B 2933 | 9445 2934 | 944A 2935 | 9463 2936 | 946B 2937 | 946D 2938 | 946F 2939 | 9471 2940 | 9472 2941 | 9578 2942 | 9579 2943 | 9586 2944 | 958C 2945 | 958D 2946 | 958E 2947 | 959F 2948 | 95A6 2949 | 95A9 2950 | 95AB 2951 | 95AC 2952 | 95B4 2953 | 95B6 2954 | 95BD 2955 | 95C8 2956 | 95CB 2957 | 95D0 2958 | 95D3 2959 | 95DA 2960 | 95DE 2961 | 961D 2962 | 962C 2963 | 9633 2964 | 9634 2965 | 963C 2966 | 9641 2967 | 9658 2968 | 9661 2969 | 9682 2970 | 9684 2971 | 969A 2972 | 969D 2973 | 96A4 2974 | 96A5 2975 | 96A9 2976 | 96AF 2977 | 96B3 2978 | 96BA 2979 | 96BD 2980 | 96D2 2981 | 96D8 2982 | 96DA 2983 | 96DD 2984 | 96DE 2985 | 96E9 2986 | 96EF 2987 | 9714 2988 | 9723 2989 | 9733 2990 | 9736 2991 | 973B 2992 | 9741 2993 | 9747 2994 | 974D 2995 | 974E 2996 | 974F 2997 | 9755 2998 | 9757 2999 | 975A 3000 | 975B 3001 | 976A 3002 | 976E 3003 | 9773 3004 | 9795 3005 | 9796 3006 | 979A 3007 | 979E 3008 | 97A2 3009 | 97AE 3010 | 97B1 3011 | 97B2 3012 | 97BA 3013 | 97BE 3014 | 97C1 3015 | 97C9 3016 | 97CC 3017 | 97D1 3018 | 97D4 3019 | 97D8 3020 | 97D9 3021 | 97DB 3022 | 97DE 3023 | 97E1 3024 | 97F1 3025 | 97F4 3026 | 9804 3027 | 980A 3028 | 980D 3029 | 980E 3030 | 9814 3031 | 9816 3032 | 981E 3033 | 9823 3034 | 9825 3035 | 982B 3036 | 9830 3037 | 9832 3038 | 9833 3039 | 9847 3040 | 9852 3041 | 9853 3042 | 9856 3043 | 9857 3044 | 9859 3045 | 985A 3046 | 9865 3047 | 9866 3048 | 986C 3049 | 98AB 3050 | 98AD 3051 | 98B0 3052 | 98B7 3053 | 98B8 3054 | 98BA 3055 | 98BB 3056 | 98BC 3057 | 98BF 3058 | 98C2 3059 | 98C7 3060 | 98C8 3061 | 98CB 3062 | 98E0 3063 | 98E1 3064 | 98E3 3065 | 98E5 3066 | 98E7 3067 | 98EA 3068 | 98F0 3069 | 98F1 3070 | 98F3 3071 | 9908 3072 | 9916 3073 | 9917 3074 | 991A 3075 | 991B 3076 | 991C 3077 | 9931 3078 | 9932 3079 | 9933 3080 | 993A 3081 | 993B 3082 | 993C 3083 | 9940 3084 | 9941 3085 | 9946 3086 | 994D 3087 | 994E 3088 | 9958 3089 | 995C 3090 | 995F 3091 | 9960 3092 | 999E 3093 | 99A3 3094 | 99A6 3095 | 99B9 3096 | 99BD 3097 | 99BF 3098 | 99C3 3099 | 99C9 3100 | 99D4 3101 | 99D9 3102 | 99DE 3103 | 99F0 3104 | 99F9 3105 | 99FC 3106 | 9A02 3107 | 9A03 3108 | 9A0A 3109 | 9A11 3110 | 9A16 3111 | 9A1A 3112 | 9A20 3113 | 9A24 3114 | 9A2D 3115 | 9A2E 3116 | 9A31 3117 | 9A36 3118 | 9A38 3119 | 9A44 3120 | 9A4A 3121 | 9A4C 3122 | 9A4E 3123 | 9A52 3124 | 9A58 3125 | 9AAF 3126 | 9AB6 3127 | 9AB7 3128 | 9AB9 3129 | 9AC1 3130 | 9AC3 3131 | 9AC6 3132 | 9ACE 3133 | 9AD0 3134 | 9AD2 3135 | 9AD5 3136 | 9AD6 3137 | 9ADC 3138 | 9AE0 3139 | 9AE5 3140 | 9AE9 3141 | 9AF9 3142 | 9B02 3143 | 9B03 3144 | 9B08 3145 | 9B0C 3146 | 9B10 3147 | 9B12 3148 | 9B16 3149 | 9B1C 3150 | 9B20 3151 | 9B2B 3152 | 9B2D 3153 | 9B33 3154 | 9B3D 3155 | 9B4B 3156 | 9B5E 3157 | 9B63 3158 | 9B65 3159 | 9B66 3160 | 9B6B 3161 | 9B6C 3162 | 9B72 3163 | 9B73 3164 | 9B75 3165 | 9B76 3166 | 9B77 3167 | 9B79 3168 | 9B84 3169 | 9B8A 3170 | 9B8F 3171 | 9B9E 3172 | 9BA6 3173 | 9BA7 3174 | 9BAC 3175 | 9BB1 3176 | 9BB2 3177 | 9BB8 3178 | 9BBE 3179 | 9BC1 3180 | 9BC7 3181 | 9BCE 3182 | 9BD8 3183 | 9BDD 3184 | 9BE5 3185 | 9BE7 3186 | 9BEA 3187 | 9BEB 3188 | 9BEE 3189 | 9BEF 3190 | 9BF3 3191 | 9BF7 3192 | 9BF8 3193 | 9BFA 3194 | 9BFD 3195 | 9C00 3196 | 9C16 3197 | 9C18 3198 | 9C19 3199 | 9C1A 3200 | 9C1D 3201 | 9C22 3202 | 9C23 3203 | 9C27 3204 | 9C29 3205 | 9C2A 3206 | 9C31 3207 | 9C36 3208 | 9C37 3209 | 9C41 3210 | 9C45 3211 | 9C49 3212 | 9C4A 3213 | 9C4F 3214 | 9C50 3215 | 9C53 3216 | 9C54 3217 | 9C58 3218 | 9C5B 3219 | 9C5C 3220 | 9C5D 3221 | 9C5F 3222 | 9C63 3223 | 9C65 3224 | 9C69 3225 | 9C6A 3226 | 9C6B 3227 | 9C6D 3228 | 9C6E 3229 | 9C70 3230 | 9C72 3231 | 9C75 3232 | 9C77 3233 | 9C7A 3234 | 9CE6 3235 | 9CF2 3236 | 9D02 3237 | 9D0B 3238 | 9D11 3239 | 9D17 3240 | 9D18 3241 | 9D1D 3242 | 9D1E 3243 | 9D32 3244 | 9D42 3245 | 9D43 3246 | 9D47 3247 | 9D4A 3248 | 9D52 3249 | 9D5F 3250 | 9D62 3251 | 9D63 3252 | 9D69 3253 | 9D6B 3254 | 9D70 3255 | 9D73 3256 | 9D76 3257 | 9D77 3258 | 9D7C 3259 | 9D7E 3260 | 9D84 3261 | 9D8A 3262 | 9D8D 3263 | 9D96 3264 | 9D99 3265 | 9DA1 3266 | 9DAC 3267 | 9DB5 3268 | 9DB9 3269 | 9DBC 3270 | 9DBD 3271 | 9DBF 3272 | 9DC0 3273 | 9DC3 3274 | 9DC7 3275 | 9DC9 3276 | 9DD6 3277 | 9DD7 3278 | 9DDA 3279 | 9DDF 3280 | 9DE0 3281 | 9DE3 3282 | 9DE7 3283 | 9DF4 3284 | 9E02 3285 | 9E07 3286 | 9E0A 3287 | 9E0D 3288 | 9E15 3289 | 9E19 3290 | 9E1C 3291 | 9E1D 3292 | 9E7B 3293 | 9E7C 3294 | 9E80 3295 | 9E85 3296 | 9E9B 3297 | 9E9E 3298 | 9EA4 3299 | 9EA8 3300 | 9EAC 3301 | 9EAF 3302 | 9EB4 3303 | 9EB5 3304 | 9EBD 3305 | 9EC3 3306 | 9ED1 3307 | 9EDF 3308 | 9EE7 3309 | 9EEE 3310 | 9EFF 3311 | 9F02 3312 | 9F03 3313 | 9F10 3314 | 9F17 3315 | 9F19 3316 | 9F2F 3317 | 9F37 3318 | 9F39 3319 | 9F3A 3320 | 9F3D 3321 | 9F41 3322 | 9F45 3323 | 9F46 3324 | 9F53 3325 | 9F55 3326 | 9F57 3327 | 9F58 3328 | 9F5D 3329 | 9F69 3330 | 9F6D 3331 | 9F70 3332 | 9F75 3333 | 9F90 3334 | 9F94 3335 | 9F97 3336 | 9FA2 3337 | F91D 3338 | F928 3339 | F929 3340 | F936 3341 | F970 3342 | F9D0 3343 | F9DC 3344 | FA0F 3345 | FA10 3346 | FA11 3347 | FA13 3348 | FA14 3349 | FA15 3350 | FA16 3351 | FA19 3352 | FA1A 3353 | FA1B 3354 | FA1F 3355 | FA20 3356 | FA21 3357 | FA22 3358 | FA24 3359 | FA26 3360 | FA30 3361 | FA31 3362 | FA32 3363 | FA33 3364 | FA34 3365 | FA35 3366 | FA36 3367 | FA37 3368 | FA38 3369 | FA39 3370 | FA3A 3371 | FA3B 3372 | FA3C 3373 | FA3D 3374 | FA3E 3375 | FA3F 3376 | FA40 3377 | FA41 3378 | FA42 3379 | FA43 3380 | FA44 3381 | FA45 3382 | FA46 3383 | FA47 3384 | FA48 3385 | FA49 3386 | FA4A 3387 | FA4B 3388 | FA4C 3389 | FA4D 3390 | FA4E 3391 | FA4F 3392 | FA50 3393 | FA51 3394 | FA52 3395 | FA53 3396 | FA54 3397 | FA55 3398 | FA56 3399 | FA57 3400 | FA58 3401 | FA59 3402 | FA5A 3403 | FA5B 3404 | FA5C 3405 | FA5D 3406 | FA5E 3407 | FA5F 3408 | FA60 3409 | FA61 3410 | FA62 3411 | FA63 3412 | FA64 3413 | FA65 3414 | FA66 3415 | FA67 3416 | FA68 3417 | FA69 3418 | FA6A 3419 | 2000B 3420 | 20089 3421 | 200A2 3422 | 200A4 3423 | 201A2 3424 | 20213 3425 | 2032B 3426 | 20371 3427 | 20381 3428 | 203F9 3429 | 2044A 3430 | 20509 3431 | 205D6 3432 | 20628 3433 | 2074F 3434 | 20807 3435 | 2083A 3436 | 208B9 3437 | 2097C 3438 | 2099D 3439 | 20AD3 3440 | 20B1D 3441 | 20B9F 3442 | 20D45 3443 | 20DE1 3444 | 20E64 3445 | 20E6D 3446 | 20E95 3447 | 20F5F 3448 | 21201 3449 | 2123D 3450 | 21255 3451 | 21274 3452 | 2127B 3453 | 212D7 3454 | 212E4 3455 | 212FD 3456 | 2131B 3457 | 21336 3458 | 21344 3459 | 213C4 3460 | 2146D 3461 | 2146E 3462 | 215D7 3463 | 21647 3464 | 216B4 3465 | 21706 3466 | 21742 3467 | 218BD 3468 | 219C3 3469 | 21C56 3470 | 21D2D 3471 | 21D45 3472 | 21D62 3473 | 21D78 3474 | 21D92 3475 | 21D9C 3476 | 21DA1 3477 | 21DB7 3478 | 21DE0 3479 | 21E33 3480 | 21E34 3481 | 21F1E 3482 | 21F76 3483 | 21FFA 3484 | 2217B 3485 | 22218 3486 | 2231E 3487 | 223AD 3488 | 226F3 3489 | 2285B 3490 | 228AB 3491 | 2298F 3492 | 22AB8 3493 | 22B46 3494 | 22B4F 3495 | 22B50 3496 | 22BA6 3497 | 22C1D 3498 | 22C24 3499 | 22DE1 3500 | 231B6 3501 | 231C3 3502 | 231C4 3503 | 231F5 3504 | 23372 3505 | 233D0 3506 | 233D2 3507 | 233D3 3508 | 233D5 3509 | 233DA 3510 | 233DF 3511 | 233E4 3512 | 2344A 3513 | 2344B 3514 | 23451 3515 | 23465 3516 | 234E4 3517 | 2355A 3518 | 23594 3519 | 235C4 3520 | 23638 3521 | 23639 3522 | 2363A 3523 | 23647 3524 | 2370C 3525 | 2371C 3526 | 2373F 3527 | 23763 3528 | 23764 3529 | 237E7 3530 | 237FF 3531 | 23824 3532 | 2383D 3533 | 23A98 3534 | 23C7F 3535 | 23CFE 3536 | 23D00 3537 | 23D0E 3538 | 23D40 3539 | 23DD3 3540 | 23DF9 3541 | 23DFA 3542 | 23F7E 3543 | 24096 3544 | 24103 3545 | 241C6 3546 | 241FE 3547 | 243BC 3548 | 24629 3549 | 246A5 3550 | 247F1 3551 | 24896 3552 | 24A4D 3553 | 24B56 3554 | 24B6F 3555 | 24C16 3556 | 24D14 3557 | 24E0E 3558 | 24E37 3559 | 24E6A 3560 | 24E8B 3561 | 2504A 3562 | 25055 3563 | 25122 3564 | 251A9 3565 | 251CD 3566 | 251E5 3567 | 2521E 3568 | 2524C 3569 | 2542E 3570 | 2548E 3571 | 254D9 3572 | 2550E 3573 | 255A7 3574 | 25771 3575 | 257A9 3576 | 257B4 3577 | 259C4 3578 | 259D4 3579 | 25AE3 3580 | 25AE4 3581 | 25AF1 3582 | 25BB2 3583 | 25C4B 3584 | 25C64 3585 | 25DA1 3586 | 25E2E 3587 | 25E56 3588 | 25E62 3589 | 25E65 3590 | 25EC2 3591 | 25ED8 3592 | 25EE8 3593 | 25F23 3594 | 25F5C 3595 | 25FD4 3596 | 25FE0 3597 | 25FFB 3598 | 2600C 3599 | 26017 3600 | 26060 3601 | 260ED 3602 | 26270 3603 | 26286 3604 | 2634C 3605 | 26402 3606 | 2667E 3607 | 266B0 3608 | 2671D 3609 | 268DD 3610 | 268EA 3611 | 26951 3612 | 2696F 3613 | 269DD 3614 | 26A1E 3615 | 26A58 3616 | 26A8C 3617 | 26AB7 3618 | 26AFF 3619 | 26C29 3620 | 26C73 3621 | 26CDD 3622 | 26E40 3623 | 26E65 3624 | 26F94 3625 | 26FF6 3626 | 26FF7 3627 | 26FF8 3628 | 270F4 3629 | 2710D 3630 | 27139 3631 | 273DA 3632 | 273DB 3633 | 273FE 3634 | 27410 3635 | 27449 3636 | 27614 3637 | 27615 3638 | 27631 3639 | 27684 3640 | 27693 3641 | 2770E 3642 | 27723 3643 | 27752 3644 | 27985 3645 | 27A84 3646 | 27BB3 3647 | 27BBE 3648 | 27BC7 3649 | 27CB8 3650 | 27DA0 3651 | 27E10 3652 | 27FB7 3653 | 2808A 3654 | 280BB 3655 | 28277 3656 | 28282 3657 | 282F3 3658 | 283CD 3659 | 2840C 3660 | 28455 3661 | 2856B 3662 | 285C8 3663 | 285C9 3664 | 286D7 3665 | 286FA 3666 | 28946 3667 | 28949 3668 | 2896B 3669 | 28987 3670 | 28988 3671 | 289BA 3672 | 289BB 3673 | 28A1E 3674 | 28A29 3675 | 28A43 3676 | 28A71 3677 | 28A99 3678 | 28ACD 3679 | 28ADD 3680 | 28AE4 3681 | 28BC1 3682 | 28BEF 3683 | 28D10 3684 | 28D71 3685 | 28DFB 3686 | 28E1F 3687 | 28E36 3688 | 28E89 3689 | 28EEB 3690 | 28F32 3691 | 28FF8 3692 | 292A0 3693 | 292B1 3694 | 29490 3695 | 295CF 3696 | 2967F 3697 | 296F0 3698 | 29719 3699 | 29750 3700 | 298C6 3701 | 29A72 3702 | 29DDB 3703 | 29E15 3704 | 29E3D 3705 | 29E49 3706 | 29E8A 3707 | 29EC4 3708 | 29EDB 3709 | 29EE9 3710 | 29FCE 3711 | 2A01A 3712 | 2A02F 3713 | 2A082 3714 | 2A0F9 3715 | 2A190 3716 | 2A38C 3717 | 2A437 3718 | 2A5F1 3719 | 2A602 3720 | 2A61A 3721 | 2A6B2 -------------------------------------------------------------------------------- /data/ISOIEC10646Annex-G-supplement-KATAKANA-compliant.txt: -------------------------------------------------------------------------------- 1 | # 2 | # @文字セット定義管理情報 3 | # 参照 URI: "https://imi.go.jp/CommonCharacterSets/ISOIEC10646Annex-G-supplement-KATAKANA-compliant" 4 | # 名称: "IMI ユーティリティ文字セット-カナ(全角)" 5 | # 説明: "本文字セット定義は、平成30年度経済産業省デジタルプラットフォーム構築事業(IMI情報共有基盤推進事業)で使用する目的で作成したものであり、IMI情報共有基盤として提供するものではありません。" 6 | # 作成者: "名称: '独立行政法人情報処理推進機構'@ja, 'IPA'@en |URL: 'https://www.ipa.go.jp/'" 7 | # 公開日付: "2019-02-04" 8 | # 9 | # @出典情報 10 | # 文書名: "ISO/IEC 10646" 11 | # 版: "第 5 版" 12 | # 説明: "KATAKANA" 13 | # 参照部分: "Annex G" 14 | # 発行元: "名称: 'ISO/IEC JTC1'|URL: 'https://www.iso.org/isoiec-jtc-1.html'" 15 | # 発行日付: "2017-12" 16 | # 17 | # @出典情報 18 | # 文書名: "7ビット及び8ビットの2バイト情報交換用符号化拡張漢字集合" 19 | # 版: "JIS X 0213:2000" 20 | # 説明: "KATAKANA" 21 | # 参照部分: "付属書4 表16 仮名名" 22 | # 発行元: "名称: '日本規格協会'|URL: 'https://www.jsa.or.jp/'" 23 | # 発行日付: "平成24年 2月20日" 24 | # 25 | 26 | # 含まれる文字の定義 27 | 30FB 28 | 309B 29 | 309C 30 | 30FD 31 | 30FE 32 | 30FC 33 | 30FF 34 | 30A0 35 | 30A1 36 | 30A2 37 | 30A3 38 | 30A4 39 | 30A5 40 | 30A6 41 | 30A7 42 | 30A8 43 | 30A9 44 | 30AA 45 | 30AB 46 | 30AC 47 | 30AD 48 | 30AE 49 | 30AF 50 | 30B0 51 | 30B1 52 | 30B2 53 | 30B3 54 | 30B4 55 | 30B5 56 | 30B6 57 | 30B7 58 | 30B8 59 | 30B9 60 | 30BA 61 | 30BB 62 | 30BC 63 | 30BD 64 | 30BE 65 | 30BF 66 | 30C0 67 | 30C1 68 | 30C2 69 | 30C3 70 | 30C4 71 | 30C5 72 | 30C6 73 | 30C7 74 | 30C8 75 | 30C9 76 | 30CA 77 | 30CB 78 | 30CC 79 | 30CD 80 | 30CE 81 | 30CF 82 | 30D0 83 | 30D1 84 | 30D2 85 | 30D3 86 | 30D4 87 | 30D5 88 | 30D6 89 | 30D7 90 | 30D8 91 | 30D9 92 | 30DA 93 | 30DB 94 | 30DC 95 | 30DD 96 | 30DE 97 | 30DF 98 | 30E0 99 | 30E1 100 | 30E2 101 | 30E3 102 | 30E4 103 | 30E5 104 | 30E6 105 | 30E7 106 | 30E8 107 | 30E9 108 | 30EA 109 | 30EB 110 | 30EC 111 | 30ED 112 | 30EE 113 | 30EF 114 | 30F0 115 | 30F1 116 | 30F2 117 | 30F3 118 | 30F4 119 | 30F5 120 | 30F6 121 | 31F0 122 | 31F1 123 | 31F2 124 | 31F3 125 | 31F4 126 | 31F5 127 | 31F6 128 | 31F7 129 | 31F8 130 | 31F9 131 | 31FA 132 | 31FB 133 | 31FC 134 | 31FD 135 | 31FE 136 | 31FF 137 | 30F7 138 | 30F8 139 | 30F9 140 | 30FA 141 | -------------------------------------------------------------------------------- /data/ISOIEC10646Annex-G-supplement-NUMERIC-compliant.txt: -------------------------------------------------------------------------------- 1 | # 2 | # @文字セット定義管理情報 3 | # 参照 URI: "https://imi.go.jp/CommonCharacterSets/ISOIEC10646Annex-G-supplement-NUMERIC-compliant" 4 | # 名称: "IMI ユーティリティ文字セット-数字" 5 | # 説明: "本文字セット定義は、平成30年度経済産業省デジタルプラットフォーム構築事業(IMI情報共有基盤推進事業)で使用する目的で作成したものであり、IMI情報共有基盤として提供するものではありません。" 6 | # 作成者: "名称: '独立行政法人情報処理推進機構'@ja, 'IPA'@en |URL: 'https://www.ipa.go.jp/'" 7 | # 公開日付: "2019-02-04" 8 | # 9 | # @出典情報 10 | # 文書名: "ISO/IEC 10646" 11 | # 版: "第 5 版" 12 | # 説明: "DIGIT ZERO to DIGIT NINE" 13 | # 参照部分: "Annex G" 14 | # 発行元: "名称: 'ISO/IEC JTC1'|URL: 'https://www.iso.org/isoiec-jtc-1.html'" 15 | # 発行日付: "2017-12" 16 | # 17 | # @出典情報 18 | # 文書名: "7ビット及び8ビットの2バイト情報交換用符号化拡張漢字集合" 19 | # 版: "JIS X 0213:2000" 20 | # 説明: "DIGIT ZERO to DIGIT NINE" 21 | # 参照部分: "付属書4 表10 数字" 22 | # 発行元: "名称: '日本規格協会'|URL: 'https://www.jsa.or.jp/'" 23 | # 発行日付: "平成24年 2月20日" 24 | # 25 | 26 | # 含まれる文字の定義 27 | 0030 28 | 0031 29 | 0032 30 | 0033 31 | 0034 32 | 0035 33 | 0036 34 | 0037 35 | 0038 36 | 0039 37 | -------------------------------------------------------------------------------- /data/README.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 | `lib/charsets.js` を作成するためのワークスペース 4 | 5 | # 手順 6 | 7 | ``` 8 | $ cd imi-data-validator/data 9 | $ node build.js ISOIEC* > ../lib/charsets.js 10 | ``` 11 | 12 | # 備考 13 | 14 | 基本的には `\u0000-\uffff` のような4桁 Unicodeの羅列で、正規表現の文字クラスとして使用することを意図している。 15 | ただし、JISX0213 等に含まれるサロゲートペアについてはひとつの文字を複数の文字として表現することになるので、 16 | `\ud800\udc00|\ud800\udc00|[\u000-\ufff]` のように、先頭部分にサロゲートペア、最後に文字クラスを付与する形となる。 17 | 正規表現としては `const re = new RegExp("^(\ud800\udc00|\ud800\udc00|[\u000-\ufff])+$");` のようにグループを併用して判定することになる。 18 | -------------------------------------------------------------------------------- /data/build.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | 3 | const classes = {}; 4 | 5 | for (let i = 2; i < process.argv.length; i++) { 6 | let key = ""; 7 | let name = ""; 8 | let lower = []; 9 | let upper = []; 10 | fs.readFileSync(process.argv[i], "UTF-8").split("\n").forEach(line => { 11 | line = line.replace(/\s/g, ""); 12 | if (line.match(/^#参照URI:"(.+)"$/)) { 13 | key = RegExp.$1; 14 | } else if (line.match(/^#名称:"(.+)"$/)) { 15 | name = RegExp.$1; 16 | } else if (line.match(/^#/) || line.length === 0) { 17 | return; 18 | } else if (line.match(/^[0-9A-Fa-f]{4}$/)) { 19 | lower.push(line); 20 | } else { 21 | upper.push(line); 22 | } 23 | }); 24 | 25 | lower.sort((a, b) => parseInt(a, 16) - parseInt(b, 16)); 26 | upper.sort((a, b) => parseInt(a, 16) - parseInt(b, 16)); 27 | 28 | const groups = []; 29 | upper.forEach(x => { 30 | const cp = parseInt(x, 16) - 0x10000; 31 | const high = 0xD800 | (cp >> 10); 32 | const low = 0xDC00 | (cp & 0x3FF); 33 | groups.push("\\u" + high.toString(16) + "\\u" + low.toString(16)); 34 | // return String.fromCharCode(high, low); 35 | }); 36 | 37 | const dst = []; 38 | lower.forEach((a, i) => { 39 | if (0 < i && i < lower.length - 1) { 40 | const a = parseInt(lower[i - 1], 16); 41 | const b = parseInt(lower[i], 16); 42 | const c = parseInt(lower[i + 1], 16); 43 | if (a + 1 === b && b + 1 === c) { 44 | dst.push("-") 45 | return; 46 | } 47 | } 48 | dst.push("\\u" + lower[i]); 49 | }); 50 | 51 | 52 | groups.push("[" + dst.join("").replace(/-+/g, "-") + "]"); 53 | 54 | classes[key] = { 55 | "moji": groups.join("|"), 56 | "name": name 57 | }; 58 | 59 | } 60 | 61 | console.log(`module.exports = ${JSON.stringify(classes, null, 2)};`); 62 | -------------------------------------------------------------------------------- /example/datamodel.imiv.txt: -------------------------------------------------------------------------------- 1 | #prefix ic: "http://imi.go.jp/ns/core/2#" 2 | datamodel; 3 | use ic:法人型>ic:表記{1..1}; 4 | use ic:法人型>ic:組織種別{0..1}; 5 | use ic:法人型>ic:組織種別>ic:識別値{1..1}; 6 | use ic:法人型>ic:組織種別>ic:表記{1..1}; 7 | use ic:法人型>ic:組織種別位置{0..1}; 8 | use ic:法人型>ic:住所{0..1}; 9 | use ic:法人型>ic:住所>ic:表記{1..1}; 10 | use ic:法人型>ic:住所>ic:都道府県{0..1}; 11 | use ic:法人型>ic:住所>ic:市区町村{0..1}; 12 | use ic:法人型>ic:住所>ic:郵便番号{0..1}{$"https://imi.go.jp/CommonCharacterSets/ISOIEC10646Annex-G-supplement-NUMERIC-compliant"}; 13 | -------------------------------------------------------------------------------- /example/graph.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 3 | "@graph": [{ 4 | "@type": "法人型", 5 | "表記": "株式会社完全充足", 6 | "組織種別位置": "前", 7 | "組織種別": { 8 | "@type": "コード型", 9 | "識別値": "301", 10 | "表記": "株式会社" 11 | }, 12 | "住所": { 13 | "@type": "住所型", 14 | "表記": "東京都千代田区麹町", 15 | "郵便番号": "1020083", 16 | "都道府県": "東京都", 17 | "市区町村": "千代田区" 18 | } 19 | }, { 20 | "@type": "法人型", 21 | "表記": "住所不定有限会社", 22 | "組織種別位置": "後", 23 | "組織種別": { 24 | "@type": "コード型", 25 | "識別値": "302", 26 | "表記": "有限会社" 27 | } 28 | }, { 29 | "表記": "最小限株式会社" 30 | }, { 31 | "@type": "法人型", 32 | "表記": "有限会社詳細住所", 33 | "住所": { 34 | "@type": "住所型", 35 | "表記": "東京都千代田区麹町2-4-8", 36 | "郵便番号": "1020083", 37 | "都道府県": "東京都", 38 | "市区町村": "千代田区", 39 | "町名": "神田", 40 | "丁目": "2", 41 | "番地": "4", 42 | "号": "8" 43 | } 44 | }, { 45 | "@type": "法人型", 46 | "表記": "全角郵便番号合同会社", 47 | "住所": { 48 | "@type": "住所型", 49 | "表記": "東京都千代田区麹町2-4-8", 50 | "郵便番号": "1020083" 51 | } 52 | }] 53 | } 54 | -------------------------------------------------------------------------------- /example/line-delimited.json.txt: -------------------------------------------------------------------------------- 1 | {"@type":"法人型","表記":"株式会社完全充足","組織種別位置":"前","組織種別":{"@type":"コード型","識別値":"301","表記":"株式会社"},"住所":{"@type":"住所型","表記":"東京都千代田区麹町","郵便番号":"1020083","都道府県":"東京都","市区町村":"千代田区"}} 2 | {"@type":"法人型","表記":"住所不定有限会社","組織種別位置":"後","組織種別":{"@type":"コード型","識別値":"302","表記":"有限会社"}} 3 | {"表記":"最小限株式会社"} 4 | {"@type":"法人型","表記":"有限会社詳細住所","住所":{"@type":"住所型","表記":"東京都千代田区麹町2-4-8","郵便番号":"1020083","都道府県":"東京都","市区町村":"千代田区","町名":"神田","丁目":"2","番地":"4","号":"8"}} 5 | {"@type":"法人型","表記":"全角郵便番号合同会社","住所":{"@type":"住所型","表記":"東京都千代田区麹町2-4-8","郵便番号":"1020083"}} 6 | -------------------------------------------------------------------------------- /example/simple.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 3 | "@type": "法人型", 4 | "表記": "株式会社完全充足", 5 | "組織種別位置": "前", 6 | "組織種別": { 7 | "@type": "コード型", 8 | "識別値": "301", 9 | "表記": "株式会社" 10 | }, 11 | "住所": { 12 | "@type": "住所型", 13 | "表記": "東京都千代田区麹町", 14 | "郵便番号": "1020083", 15 | "都道府県": "東京都", 16 | "市区町村": "千代田区" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lib/util.js: -------------------------------------------------------------------------------- 1 | const charsets = require("./charsets"); 2 | const IMIMojiConverter = require("imi-moji-converter"); 3 | 4 | const SUCCESS = { 5 | "種別": "INFO", 6 | }; 7 | 8 | module.exports = { 9 | datatype: function(def, val) { 10 | switch (def) { 11 | case "xsd:integer": 12 | return val.match(/^(0|[1-9][0-9]*|-[1-9][0-9]*)$/) ? SUCCESS : { 13 | "種別": "ERROR", 14 | "説明": `xsd:integer ではありません` 15 | }; 16 | case "xsd:nonNegativeInteger": 17 | return val.match(/^(0|[1-9][0-9]*)$/) ? SUCCESS : { 18 | "種別": "ERROR", 19 | "説明": `xsd:nonNegativeInteger ではありません` 20 | }; 21 | case "xsd:date": 22 | return val.match(/^[0-9]+-[0-9][0-9]-[0-9][0-9]$/) ? SUCCESS : { 23 | "種別": "ERROR", 24 | "説明": `xsd:date ではありません` 25 | }; 26 | } 27 | return SUCCESS; 28 | }, 29 | eq: function(def, val) { 30 | return (def === val) ? SUCCESS : { 31 | "種別": "ERROR", 32 | "説明": `${def} でなければなりません` 33 | }; 34 | }, 35 | lt: function(def, val) { 36 | if (isNaN(parseInt(val))) return { 37 | "種別": "ERROR", 38 | "説明": `数値ではありません` 39 | }; 40 | return (parseInt(val) < parseInt(def)) ? SUCCESS : { 41 | "種別": "ERROR", 42 | "説明": `${def} より小さくなければいけません` 43 | }; 44 | }, 45 | le: function(def, val) { 46 | if (isNaN(parseInt(val))) return { 47 | "種別": "ERROR", 48 | "説明": `数値ではありません` 49 | }; 50 | return (parseInt(val) <= parseInt(def)) ? SUCCESS : { 51 | "種別": "ERROR", 52 | "説明": `${def} 以下でなければいけません` 53 | }; 54 | }, 55 | gt: function(def, val) { 56 | if (isNaN(parseInt(val))) return { 57 | "種別": "ERROR", 58 | "説明": `数値ではありません` 59 | }; 60 | return (parseInt(val) > parseInt(def)) ? SUCCESS : { 61 | "種別": "ERROR", 62 | "説明": `${def} より大きくなければいけません` 63 | }; 64 | }, 65 | ge: function(def, val) { 66 | if (isNaN(parseInt(val))) return { 67 | "種別": "ERROR", 68 | "説明": `数値ではありません` 69 | }; 70 | return (parseInt(val) >= parseInt(def)) ? SUCCESS : { 71 | "種別": "ERROR", 72 | "説明": `${def} 以上でなければいけません` 73 | }; 74 | }, 75 | pattern: function(def, val) { 76 | return new RegExp(def).test(val) ? SUCCESS : { 77 | "種別": "ERROR", 78 | "説明": `正規表現 ${def} に適合しません` 79 | }; 80 | }, 81 | charset: function(def, val) { 82 | const token = def.replace(/\s/g, ""); 83 | 84 | const rec = []; 85 | const non = []; 86 | 87 | token.split("|").forEach(x => { 88 | const flag = (x.indexOf("[NotRecommended]") === 0); 89 | const uri = x.replace("[NotRecommended]", ""); 90 | if (charsets[uri] !== undefined) 91 | (flag ? non : rec).push(charsets[uri]); 92 | }); 93 | 94 | // 推奨だけの場合 95 | if (rec.length > 0 && non.length === 0) { 96 | const mojis = []; 97 | const names = []; 98 | rec.forEach(x => { 99 | mojis.push(x.moji); 100 | names.push(x.name); 101 | }); 102 | 103 | const pattern = new RegExp("^(" + mojis.join("|") + ")*$"); 104 | if (pattern.test(val)) return SUCCESS; 105 | 106 | const error = { 107 | "種別": "ERROR", 108 | "説明": `[${names.join(",")}] で規定されていない文字が使用されています`, 109 | }; 110 | 111 | if (token === "https://imi.go.jp/CommonCharacterSets/ISOIEC10646Annex-G-supplement-KATAKANA-compliant") { 112 | const conv = IMIMojiConverter.toFullWidth(val); 113 | if (pattern.test(conv)) 114 | return [error, { 115 | "種別": "WARNING", 116 | "説明": `[${names.join(",")}] で規定されていない文字が使用されていましたが、半角カナ/全角カナ変換によって修正されました`, 117 | "値": conv 118 | }]; 119 | } 120 | 121 | if (token === "https://imi.go.jp/CommonCharacterSets/ISOIEC10646Annex-G-supplement-NUMERIC-compliant") { 122 | const conv = IMIMojiConverter.toHalfWidth(val); 123 | if (pattern.test(conv)) 124 | return [error, { 125 | "種別": "WARNING", 126 | "説明": `[${names.join(",")}] で規定されていない文字が使用されていましたが、全角数字/半角数字変換によって修正されました`, 127 | "値": conv 128 | }]; 129 | } 130 | return error; 131 | 132 | } 133 | 134 | // 非推奨だけの場合 135 | if (rec.length === 0 && non.length > 0) { 136 | const mojis = []; 137 | const names = []; 138 | non.forEach(x => { 139 | mojis.push(x.moji); 140 | names.push(x.name); 141 | }); 142 | const pattern = new RegExp("(" + mojis.join("|") + ")"); 143 | return pattern.test(val) ? { 144 | "種別": "WARNING", 145 | "説明": `[${names.join(",")}] で規定された非推奨文字が使用されています` 146 | } : SUCCESS; 147 | 148 | } 149 | 150 | // 推奨と非推奨の複合 151 | if (rec.length > 0 && non.length > 0) { 152 | const mix = rec.concat(non); 153 | const pattern1 = new RegExp("^(" + mix.map(a => a.moji).join("|") + ")*$"); 154 | const names1 = mix.map(a => a.name).join(","); 155 | if (!pattern1.test(val)) { 156 | return { 157 | "種別": "ERROR", 158 | "説明": `[${names1}] で規定されていない文字が使用されています` 159 | }; 160 | } 161 | const pattern2 = new RegExp("(" + non.map(a => a.moji).join("|") + ")"); 162 | const names2 = non.map(a => a.name).join(","); 163 | if (pattern2.test(val)) { 164 | return { 165 | "種別": "WARNING", 166 | "説明": `[${names2}] で規定された非推奨文字が使用されています` 167 | }; 168 | } 169 | return SUCCESS; 170 | } 171 | 172 | return SUCCESS; 173 | 174 | 175 | 176 | } 177 | }; 178 | -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | const Parser = require('imiv-parser'); 2 | const parse = function(imiv) { 3 | const prefix = {}; 4 | const dig = function(a) { 5 | a.restriction = a.restriction || []; 6 | a.restriction.forEach(b => { 7 | dig(b); 8 | if (b.type === "type") a.typeRestriction = b.pname; 9 | if (b.type === "cardinality") a.cardinality = b; 10 | }); 11 | if (a.prefix && a.name && prefix[a.prefix]) a.pname = `${a.prefix}:${a.name}`; 12 | if (a.class) dig(a.class); 13 | if (a.property) dig(a.property); 14 | if (a.next) dig(a.next); 15 | return a; 16 | }; 17 | return Parser.parse(imiv).map(a => { 18 | a.metadata = a.metadata || []; 19 | a.metadata.filter(b => b.type === "prefix").forEach(b => { 20 | prefix[b.prefix] = b.data; 21 | }); 22 | return dig(a); 23 | }); 24 | }; 25 | 26 | const Util = require("./lib/util"); 27 | 28 | const isDatatype = (pname) => ["xsd:", "uncefact", "ic:電話番号型"].find(a => pname.indexOf(a) === 0); 29 | const normalize = (pname) => pname.replace(/^ic:/, ""); 30 | const unnormalize = (pname) => pname.indexOf(":") === -1 ? "ic:" + pname : pname; 31 | 32 | function Logger() { 33 | this.count = { 34 | "INFO": 0, 35 | "WARNING": 0, 36 | "ERROR": 0 37 | }; 38 | return this; 39 | } 40 | 41 | Logger.prototype = { 42 | log: function(target, level, message) { 43 | const now = new Date(); 44 | now.setHours(now.getHours() + 9); 45 | const content = { 46 | "@type": "hj:更新履歴型", 47 | "hj:更新者": { 48 | "@type": "実体型", 49 | "表記": "IMIデータバリデーションコンポーネント" 50 | }, 51 | "種別": level, 52 | "説明": message, 53 | "日時": { 54 | "@type": "日時型", 55 | "標準型日時": now.toISOString().replace(/Z$/, "+09:00") 56 | } 57 | }; 58 | this.count[level]++; 59 | if (target["メタデータ"] === undefined) target["メタデータ"] = content; 60 | else if (Array.isArray(target["メタデータ"])) target["メタデータ"].push(content); 61 | else target["メタデータ"] = [target["メタデータ"], content]; 62 | }, 63 | reset: function() { 64 | this.count = { 65 | "INFO": 0, 66 | "WARNING": 0, 67 | "ERROR": 0 68 | }; 69 | } 70 | }; 71 | 72 | // datamodel は必要な語彙とデータモデルを連結した語彙記法の文字列 73 | // instance を validate するための関数を返す 74 | module.exports = function(datamodel, options) { 75 | 76 | const __DISABLE_AUTO_FIX__ = !!(options && options["disable_auto_fix"] === true); 77 | 78 | const definitions = parse(datamodel); 79 | 80 | const isSubClassOf = (a, b) => { 81 | if (a === b) return true; 82 | const d = definitions.find(x => x.pname === a); 83 | if (d == undefined || d.typeRestriction === undefined) return false; 84 | return isSubClassOf(d.typeRestriction, b); 85 | }; 86 | 87 | // use 定義がら導かれる、ツリー型のデータモデル 88 | const tree = (() => { 89 | const a = {}; 90 | const dig = (src, parent) => { 91 | if (!src) return; 92 | const name = src.pname; 93 | if (parent[name] === undefined) parent[name] = []; 94 | let child = parent[name].find(a => src.group ? a["@group"] === src.group : a["@group"] === undefined); 95 | if (child === undefined) { 96 | child = { 97 | restriction: [] 98 | }; 99 | if (src.group) child["@group"] = src.group; 100 | parent[name].push(child); 101 | } 102 | child.restriction = child.restriction.concat(src.restriction); 103 | if (src.typeRestriction) child.typeRestriction = src.typeRestriction; 104 | if (src.cardinality) child.cardinality = src.cardinality; 105 | 106 | dig(src.next, child); 107 | }; 108 | definitions.filter(use => use.type === "use").forEach(use => { 109 | a["@type"] = use.class.pname; 110 | dig(use.class.next, a); 111 | }); 112 | return a; 113 | })(); 114 | 115 | // 関数を返す 116 | return function(instance) { 117 | 118 | // 入力インスタンスのコピーに対して作業する 119 | instance = JSON.parse(JSON.stringify(instance)); 120 | const logger = new Logger(); 121 | 122 | const dig = (focus, src, dst, depth) => { 123 | if (src["メタデータ"] !== undefined) dst["メタデータ"] = src["メタデータ"]; 124 | // ルートクラス 125 | if (depth === 0) { 126 | const name = normalize(focus["@type"]); 127 | if (dst["@type"] === undefined) { 128 | if (src["@type"] === undefined) { 129 | // クラス名の補完 130 | // 修復 NG の場合はエラーとして終了 131 | if (__DISABLE_AUTO_FIX__) { 132 | Object.assign(dst, src); 133 | logger.log(dst, "ERROR", "ルートクラスが指定されていません"); 134 | return; 135 | } 136 | dst["@type"] = name; 137 | logger.log(dst, "WARNING", "ルートクラスが指定されていなかったのでデータモデル定義のルートクラスから補完しました"); 138 | } else if (src["@type"] !== name) { 139 | // クラス名が間違っているのでエラーとして記録 140 | // ルートクラスはサブクラスを認めないこととするので、完全一致のみ 141 | Object.assign(dst, src); 142 | logger.log(dst, "ERROR", "ルートクラスがデータモデル定義のルートクラスと一致しません"); 143 | return; 144 | } else { 145 | dst["@type"] = name; 146 | } 147 | } 148 | } 149 | 150 | // データモデルで必須のプロパティが存在しない場合はエラー 151 | Object.keys(focus).filter(key => key.indexOf("@") !== 0).forEach(key => { 152 | const name = unnormalize(key); 153 | const definition = definitions.find(a => a.pname === key); 154 | //語彙定義(クラスまたはプロパティ)が見つからない場合は中止 155 | if (definition === undefined) return; 156 | // プロパティ+グループに対して iterate 157 | focus[key].forEach(def => { 158 | 159 | // コピー元の値リストを作成 160 | let values = []; 161 | const name = normalize(key); 162 | if (src[name] === undefined) { 163 | // 164 | } else if (Array.isArray(src[name])) { 165 | values = src[name]; 166 | } else { 167 | values.push(src[name]); 168 | } 169 | 170 | // グループによるインスタンスのフィルタリング条件 171 | if (focus[key].length > 1 && def["ic:種別"] !== undefined) { 172 | values = values.filter(a => { 173 | return a["種別"] === def["@group"]; 174 | }); 175 | } 176 | 177 | // カーディナリティの評価 178 | const length = values.length; //value === undefined ? 0 : (Array.isArray(value) ? value.length : 1); 179 | const cardinality = def.cardinality || definition.cardinality || { 180 | min: 0 181 | }; 182 | 183 | if (cardinality.min !== undefined && cardinality.min > length) { 184 | if (def["@group"] !== undefined) 185 | logger.log(dst, "ERROR", `プロパティ ${name} (グループ ${def["@group"]}) の値が最低 ${cardinality.min} 必要ですが、不足しています`); 186 | else 187 | logger.log(dst, "ERROR", `プロパティ ${name} の値が最低 ${cardinality.min} 必要ですが、不足しています`); 188 | return; 189 | } 190 | if (cardinality.max !== undefined && cardinality.max < length) { 191 | if (def["@group"] !== undefined) 192 | logger.log(dst, "ERROR", `プロパティ ${name} (グループ ${def["@group"]}) の値は最大 ${cardinality.min} 個が許容されますが、過剰です`); 193 | else logger.log(dst, "ERROR", `プロパティ ${name} の値は最大 ${cardinality.min} 個が許容されますが、過剰です`); 194 | return; 195 | } 196 | }); 197 | }); 198 | 199 | 200 | // データモデルに存在しないプロパティは削除と警告 201 | const removed = []; 202 | Object.keys(src).filter(key => key.indexOf("@") !== 0).forEach(key => { 203 | if (key === "メタデータ") return; 204 | const name = unnormalize(key); 205 | if (focus[name] === undefined) removed.push(key); 206 | }); 207 | if (removed.length > 0) { 208 | if (__DISABLE_AUTO_FIX__) { 209 | Object.assign(dst, src); 210 | logger.log(dst, "ERROR", `プロパティ ${removed.join(",")} はデータモデルで許可されていません`); 211 | return; 212 | } else { 213 | logger.log(dst, "WARNING", `プロパティ ${removed.join(",")} はデータモデルに適合しないので削除されました`); 214 | } 215 | } 216 | 217 | // コピー元の値に対して探索 218 | Object.keys(src).filter(name => name.indexOf("@") !== 0).forEach(name => { 219 | if (name === "メタデータ") return; 220 | const key = unnormalize(name); 221 | const val = src[name]; 222 | const definition = definitions.find(a => a.pname === key); 223 | if (definition === undefined) return; 224 | if (isDatatype(definition.typeRestriction)) { 225 | let values = Array.isArray(val) ? val : [val]; 226 | // 値が存在したとしてもデータモデルに定義がない場合はここで排除される 227 | if (focus[key] && focus[key][0]) { 228 | // データ型に対するチェック 229 | values = values.map(b => { 230 | const c = Util.datatype(definition.typeRestriction, b); 231 | if (c["種別"] !== "INFO") logger.log(dst, c["種別"], `プロパティ ${name} は ${c["説明"]}`); 232 | return b; 233 | }); 234 | 235 | // 個別の制約に対するチェック 236 | focus[key][0].restriction.forEach(a => { 237 | values = values.map(b => { 238 | if (Util[a.type] === undefined) return b; 239 | let c = Util[a.type](a.data, b); 240 | if (Array.isArray(c)) 241 | c = c.find(d => d["種別"] === (__DISABLE_AUTO_FIX__ ? "ERROR" : "WARNING")); 242 | if (c["種別"] !== "INFO") logger.log(dst, c["種別"], `プロパティ ${name} は ${c["説明"]}`); 243 | return c["値"] || b; 244 | }); 245 | }); 246 | dst[name] = Array.isArray(val) ? values : values[0]; 247 | } 248 | return; 249 | } else { 250 | let values = Array.isArray(val) ? val : [val]; 251 | values = values.map(obj => { 252 | const def = (focus[key] || []).find(f => { 253 | if (focus[key].length < 2) return true; 254 | return f["@group"] === obj["種別"]; 255 | }); 256 | if (def === undefined) return obj; 257 | 258 | const typeRestriction = def.typeRestriction || definition.typeRestriction; 259 | 260 | const tmp = {}; 261 | 262 | if (obj["@type"] === undefined) { 263 | if (__DISABLE_AUTO_FIX__) { 264 | Object.assign(tmp, obj); 265 | logger.log(tmp, "ERROR", "クラスが指定されてません"); 266 | return tmp; 267 | } 268 | // クラス名の補完が発生したので修復してログを記録 269 | tmp["@type"] = normalize(typeRestriction); 270 | logger.log(tmp, "WARNING", "クラスが指定されていなかったのでデータモデル定義から補完しました"); 271 | dig(def, obj, tmp, depth + 1); 272 | } else if (isSubClassOf(unnormalize(obj["@type"]), typeRestriction)) { 273 | // 正常なクラス名が指定されている 274 | // サブクラスであっても構わない(データモデルの抽象クラスをインスタンスで具体化する場合) 275 | tmp["@type"] = obj["@type"]; 276 | dig(def, obj, tmp, depth + 1); 277 | } else { 278 | // クラス名指定がおかしいのでエラーを記録して中止 279 | Object.assign(tmp, obj); 280 | logger.log(tmp, "ERROR", "指定されたクラスはデータモデル定義に適合しません"); 281 | } 282 | 283 | return tmp; 284 | }); 285 | 286 | dst[name] = Array.isArray(val) ? values : values[0]; 287 | } 288 | 289 | 290 | }); 291 | }; 292 | 293 | const done = (instance["@graph"] || [instance]).map(src => { 294 | const dst = {}; 295 | logger.reset(); 296 | dig(tree, src, dst, 0); 297 | if (logger.count.ERROR > 0 && logger.count.WARNING > 0) 298 | logger.log(dst, "ERROR", `${logger.count.ERROR} 件のエラーと ${logger.count.WARNING} 件の修正可能な問題が見つかりました。このインスタンスはデータモデルには適合しないので修正が必要です。`); 299 | else if (logger.count.ERROR > 0) 300 | logger.log(dst, "ERROR", `${logger.count.ERROR} 件のエラーが見つかりました。このインスタンスはデータモデルには適合しないので修正が必要です。`); 301 | else if (logger.count.WARNING > 0) 302 | logger.log(dst, "WARNING", `${logger.count.WARNING} 件の修正可能な問題が見つかりました。このインスタンスはデータモデルに適合しますが、自動修正された箇所を確認してください。`); 303 | else 304 | logger.log(dst, "INFO", "このインスタンスはデータモデルに適合しています"); 305 | 306 | // 異常系: ルートクラスに間違いがあった場合、@context もコピーされる場合があるのでここで削除しておく 307 | delete dst["@context"]; 308 | return dst; 309 | }); 310 | 311 | const output = {}; 312 | 313 | if (instance["@context"] === undefined) output["@context"] = []; 314 | else if (Array.isArray(instance["@context"])) output["@context"] = instance["@context"]; 315 | else output["@context"] = [instance["@context"]]; 316 | 317 | [ 318 | "https://imi.go.jp/ns/core/context.jsonld", 319 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 320 | ].filter(a => output["@context"].indexOf(a) === -1).forEach(a => { 321 | output["@context"].push(a); 322 | }); 323 | 324 | if (instance["@graph"] !== undefined) output["@graph"] = done; 325 | else Object.assign(output, done[0]); 326 | 327 | 328 | return output; 329 | 330 | }; 331 | 332 | }; 333 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "imi-data-validator", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@ungap/promise-all-settled": { 8 | "version": "1.1.2", 9 | "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", 10 | "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", 11 | "dev": true 12 | }, 13 | "ansi-colors": { 14 | "version": "4.1.1", 15 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", 16 | "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", 17 | "dev": true 18 | }, 19 | "ansi-regex": { 20 | "version": "3.0.0", 21 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 22 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", 23 | "dev": true 24 | }, 25 | "ansi-styles": { 26 | "version": "4.3.0", 27 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 28 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 29 | "dev": true, 30 | "requires": { 31 | "color-convert": "^2.0.1" 32 | } 33 | }, 34 | "anymatch": { 35 | "version": "3.1.1", 36 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", 37 | "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", 38 | "dev": true, 39 | "requires": { 40 | "normalize-path": "^3.0.0", 41 | "picomatch": "^2.0.4" 42 | } 43 | }, 44 | "argparse": { 45 | "version": "1.0.10", 46 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 47 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 48 | "dev": true, 49 | "requires": { 50 | "sprintf-js": "~1.0.2" 51 | } 52 | }, 53 | "assertion-error": { 54 | "version": "1.1.0", 55 | "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", 56 | "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", 57 | "dev": true 58 | }, 59 | "balanced-match": { 60 | "version": "1.0.0", 61 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 62 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 63 | "dev": true 64 | }, 65 | "binary-extensions": { 66 | "version": "2.1.0", 67 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", 68 | "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", 69 | "dev": true 70 | }, 71 | "brace-expansion": { 72 | "version": "1.1.11", 73 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 74 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 75 | "dev": true, 76 | "requires": { 77 | "balanced-match": "^1.0.0", 78 | "concat-map": "0.0.1" 79 | } 80 | }, 81 | "braces": { 82 | "version": "3.0.2", 83 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 84 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 85 | "dev": true, 86 | "requires": { 87 | "fill-range": "^7.0.1" 88 | } 89 | }, 90 | "browser-stdout": { 91 | "version": "1.3.1", 92 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", 93 | "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", 94 | "dev": true 95 | }, 96 | "camelcase": { 97 | "version": "5.3.1", 98 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", 99 | "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", 100 | "dev": true 101 | }, 102 | "chai": { 103 | "version": "4.2.0", 104 | "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", 105 | "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", 106 | "dev": true, 107 | "requires": { 108 | "assertion-error": "^1.1.0", 109 | "check-error": "^1.0.2", 110 | "deep-eql": "^3.0.1", 111 | "get-func-name": "^2.0.0", 112 | "pathval": "^1.1.0", 113 | "type-detect": "^4.0.5" 114 | } 115 | }, 116 | "chalk": { 117 | "version": "4.1.0", 118 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", 119 | "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", 120 | "dev": true, 121 | "requires": { 122 | "ansi-styles": "^4.1.0", 123 | "supports-color": "^7.1.0" 124 | } 125 | }, 126 | "check-error": { 127 | "version": "1.0.2", 128 | "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", 129 | "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", 130 | "dev": true 131 | }, 132 | "chokidar": { 133 | "version": "3.4.3", 134 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", 135 | "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", 136 | "dev": true, 137 | "requires": { 138 | "anymatch": "~3.1.1", 139 | "braces": "~3.0.2", 140 | "fsevents": "~2.1.2", 141 | "glob-parent": "~5.1.0", 142 | "is-binary-path": "~2.1.0", 143 | "is-glob": "~4.0.1", 144 | "normalize-path": "~3.0.0", 145 | "readdirp": "~3.5.0" 146 | } 147 | }, 148 | "cliui": { 149 | "version": "5.0.0", 150 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", 151 | "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", 152 | "dev": true, 153 | "requires": { 154 | "string-width": "^3.1.0", 155 | "strip-ansi": "^5.2.0", 156 | "wrap-ansi": "^5.1.0" 157 | }, 158 | "dependencies": { 159 | "ansi-regex": { 160 | "version": "4.1.0", 161 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 162 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", 163 | "dev": true 164 | }, 165 | "string-width": { 166 | "version": "3.1.0", 167 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 168 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 169 | "dev": true, 170 | "requires": { 171 | "emoji-regex": "^7.0.1", 172 | "is-fullwidth-code-point": "^2.0.0", 173 | "strip-ansi": "^5.1.0" 174 | } 175 | }, 176 | "strip-ansi": { 177 | "version": "5.2.0", 178 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 179 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 180 | "dev": true, 181 | "requires": { 182 | "ansi-regex": "^4.1.0" 183 | } 184 | } 185 | } 186 | }, 187 | "color-convert": { 188 | "version": "2.0.1", 189 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 190 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 191 | "dev": true, 192 | "requires": { 193 | "color-name": "~1.1.4" 194 | } 195 | }, 196 | "color-name": { 197 | "version": "1.1.4", 198 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 199 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 200 | "dev": true 201 | }, 202 | "concat-map": { 203 | "version": "0.0.1", 204 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 205 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 206 | "dev": true 207 | }, 208 | "debug": { 209 | "version": "4.2.0", 210 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", 211 | "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", 212 | "dev": true, 213 | "requires": { 214 | "ms": "2.1.2" 215 | } 216 | }, 217 | "decamelize": { 218 | "version": "1.2.0", 219 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 220 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", 221 | "dev": true 222 | }, 223 | "deep-eql": { 224 | "version": "3.0.1", 225 | "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", 226 | "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", 227 | "dev": true, 228 | "requires": { 229 | "type-detect": "^4.0.0" 230 | } 231 | }, 232 | "diff": { 233 | "version": "4.0.2", 234 | "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", 235 | "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", 236 | "dev": true 237 | }, 238 | "emoji-regex": { 239 | "version": "7.0.3", 240 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", 241 | "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", 242 | "dev": true 243 | }, 244 | "escape-string-regexp": { 245 | "version": "4.0.0", 246 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 247 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 248 | "dev": true 249 | }, 250 | "esprima": { 251 | "version": "4.0.1", 252 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 253 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 254 | "dev": true 255 | }, 256 | "fill-range": { 257 | "version": "7.0.1", 258 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 259 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 260 | "dev": true, 261 | "requires": { 262 | "to-regex-range": "^5.0.1" 263 | } 264 | }, 265 | "find-up": { 266 | "version": "5.0.0", 267 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", 268 | "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", 269 | "dev": true, 270 | "requires": { 271 | "locate-path": "^6.0.0", 272 | "path-exists": "^4.0.0" 273 | } 274 | }, 275 | "flat": { 276 | "version": "5.0.2", 277 | "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", 278 | "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", 279 | "dev": true 280 | }, 281 | "fs.realpath": { 282 | "version": "1.0.0", 283 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 284 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 285 | "dev": true 286 | }, 287 | "fsevents": { 288 | "version": "2.1.3", 289 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", 290 | "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", 291 | "dev": true, 292 | "optional": true 293 | }, 294 | "get-caller-file": { 295 | "version": "2.0.5", 296 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 297 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 298 | "dev": true 299 | }, 300 | "get-func-name": { 301 | "version": "2.0.0", 302 | "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", 303 | "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", 304 | "dev": true 305 | }, 306 | "glob": { 307 | "version": "7.1.6", 308 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 309 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 310 | "dev": true, 311 | "requires": { 312 | "fs.realpath": "^1.0.0", 313 | "inflight": "^1.0.4", 314 | "inherits": "2", 315 | "minimatch": "^3.0.4", 316 | "once": "^1.3.0", 317 | "path-is-absolute": "^1.0.0" 318 | } 319 | }, 320 | "glob-parent": { 321 | "version": "5.1.1", 322 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", 323 | "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", 324 | "dev": true, 325 | "requires": { 326 | "is-glob": "^4.0.1" 327 | } 328 | }, 329 | "growl": { 330 | "version": "1.10.5", 331 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", 332 | "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", 333 | "dev": true 334 | }, 335 | "has-flag": { 336 | "version": "4.0.0", 337 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 338 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 339 | "dev": true 340 | }, 341 | "he": { 342 | "version": "1.2.0", 343 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 344 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", 345 | "dev": true 346 | }, 347 | "imi-moji-converter": { 348 | "version": "github:IMI-Tool-Project/imi-moji-converter#88607e6f1948d9091cf9a6b3a808bb9572af1fe9", 349 | "from": "github:IMI-Tool-Project/imi-moji-converter", 350 | "requires": { 351 | "moji": "^0.5.1" 352 | } 353 | }, 354 | "imiv-parser": { 355 | "version": "1.0.1", 356 | "resolved": "https://registry.npmjs.org/imiv-parser/-/imiv-parser-1.0.1.tgz", 357 | "integrity": "sha512-o5IooeV4QKFGK0cptjlOHOjtDY91KI0L+HB4xUZMfgsIBeoylXVnE284x53JubinotPvdmyzbasVAZq/0g44+g==" 358 | }, 359 | "inflight": { 360 | "version": "1.0.6", 361 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 362 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 363 | "dev": true, 364 | "requires": { 365 | "once": "^1.3.0", 366 | "wrappy": "1" 367 | } 368 | }, 369 | "inherits": { 370 | "version": "2.0.4", 371 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 372 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 373 | "dev": true 374 | }, 375 | "is-binary-path": { 376 | "version": "2.1.0", 377 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 378 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 379 | "dev": true, 380 | "requires": { 381 | "binary-extensions": "^2.0.0" 382 | } 383 | }, 384 | "is-extglob": { 385 | "version": "2.1.1", 386 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 387 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 388 | "dev": true 389 | }, 390 | "is-fullwidth-code-point": { 391 | "version": "2.0.0", 392 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 393 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 394 | "dev": true 395 | }, 396 | "is-glob": { 397 | "version": "4.0.1", 398 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", 399 | "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", 400 | "dev": true, 401 | "requires": { 402 | "is-extglob": "^2.1.1" 403 | } 404 | }, 405 | "is-number": { 406 | "version": "7.0.0", 407 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 408 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 409 | "dev": true 410 | }, 411 | "is-plain-obj": { 412 | "version": "2.1.0", 413 | "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", 414 | "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", 415 | "dev": true 416 | }, 417 | "isexe": { 418 | "version": "2.0.0", 419 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 420 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 421 | "dev": true 422 | }, 423 | "js-yaml": { 424 | "version": "3.14.0", 425 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", 426 | "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", 427 | "dev": true, 428 | "requires": { 429 | "argparse": "^1.0.7", 430 | "esprima": "^4.0.0" 431 | } 432 | }, 433 | "locate-path": { 434 | "version": "6.0.0", 435 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", 436 | "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", 437 | "dev": true, 438 | "requires": { 439 | "p-locate": "^5.0.0" 440 | } 441 | }, 442 | "log-symbols": { 443 | "version": "4.0.0", 444 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", 445 | "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", 446 | "dev": true, 447 | "requires": { 448 | "chalk": "^4.0.0" 449 | } 450 | }, 451 | "minimatch": { 452 | "version": "3.0.4", 453 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 454 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 455 | "dev": true, 456 | "requires": { 457 | "brace-expansion": "^1.1.7" 458 | } 459 | }, 460 | "mocha": { 461 | "version": "8.2.1", 462 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.2.1.tgz", 463 | "integrity": "sha512-cuLBVfyFfFqbNR0uUKbDGXKGk+UDFe6aR4os78XIrMQpZl/nv7JYHcvP5MFIAb374b2zFXsdgEGwmzMtP0Xg8w==", 464 | "dev": true, 465 | "requires": { 466 | "@ungap/promise-all-settled": "1.1.2", 467 | "ansi-colors": "4.1.1", 468 | "browser-stdout": "1.3.1", 469 | "chokidar": "3.4.3", 470 | "debug": "4.2.0", 471 | "diff": "4.0.2", 472 | "escape-string-regexp": "4.0.0", 473 | "find-up": "5.0.0", 474 | "glob": "7.1.6", 475 | "growl": "1.10.5", 476 | "he": "1.2.0", 477 | "js-yaml": "3.14.0", 478 | "log-symbols": "4.0.0", 479 | "minimatch": "3.0.4", 480 | "ms": "2.1.2", 481 | "nanoid": "3.1.12", 482 | "serialize-javascript": "5.0.1", 483 | "strip-json-comments": "3.1.1", 484 | "supports-color": "7.2.0", 485 | "which": "2.0.2", 486 | "wide-align": "1.1.3", 487 | "workerpool": "6.0.2", 488 | "yargs": "13.3.2", 489 | "yargs-parser": "13.1.2", 490 | "yargs-unparser": "2.0.0" 491 | } 492 | }, 493 | "moji": { 494 | "version": "0.5.1", 495 | "resolved": "https://registry.npmjs.org/moji/-/moji-0.5.1.tgz", 496 | "integrity": "sha1-CI7s0cIsjzGiQK3PnJXlTzPrVPs=", 497 | "requires": { 498 | "object-assign": "^3.0.0" 499 | } 500 | }, 501 | "ms": { 502 | "version": "2.1.2", 503 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 504 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 505 | "dev": true 506 | }, 507 | "nanoid": { 508 | "version": "3.1.12", 509 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.12.tgz", 510 | "integrity": "sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A==", 511 | "dev": true 512 | }, 513 | "normalize-path": { 514 | "version": "3.0.0", 515 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 516 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 517 | "dev": true 518 | }, 519 | "object-assign": { 520 | "version": "3.0.0", 521 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", 522 | "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=" 523 | }, 524 | "once": { 525 | "version": "1.4.0", 526 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 527 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 528 | "dev": true, 529 | "requires": { 530 | "wrappy": "1" 531 | } 532 | }, 533 | "p-limit": { 534 | "version": "3.1.0", 535 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", 536 | "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", 537 | "dev": true, 538 | "requires": { 539 | "yocto-queue": "^0.1.0" 540 | } 541 | }, 542 | "p-locate": { 543 | "version": "5.0.0", 544 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", 545 | "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", 546 | "dev": true, 547 | "requires": { 548 | "p-limit": "^3.0.2" 549 | } 550 | }, 551 | "p-try": { 552 | "version": "2.2.0", 553 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 554 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", 555 | "dev": true 556 | }, 557 | "path-exists": { 558 | "version": "4.0.0", 559 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 560 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 561 | "dev": true 562 | }, 563 | "path-is-absolute": { 564 | "version": "1.0.1", 565 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 566 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 567 | "dev": true 568 | }, 569 | "pathval": { 570 | "version": "1.1.0", 571 | "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", 572 | "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", 573 | "dev": true 574 | }, 575 | "picomatch": { 576 | "version": "2.2.2", 577 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", 578 | "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", 579 | "dev": true 580 | }, 581 | "randombytes": { 582 | "version": "2.1.0", 583 | "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", 584 | "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", 585 | "dev": true, 586 | "requires": { 587 | "safe-buffer": "^5.1.0" 588 | } 589 | }, 590 | "readdirp": { 591 | "version": "3.5.0", 592 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", 593 | "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", 594 | "dev": true, 595 | "requires": { 596 | "picomatch": "^2.2.1" 597 | } 598 | }, 599 | "require-directory": { 600 | "version": "2.1.1", 601 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 602 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", 603 | "dev": true 604 | }, 605 | "require-main-filename": { 606 | "version": "2.0.0", 607 | "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", 608 | "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", 609 | "dev": true 610 | }, 611 | "safe-buffer": { 612 | "version": "5.2.1", 613 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 614 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 615 | "dev": true 616 | }, 617 | "serialize-javascript": { 618 | "version": "5.0.1", 619 | "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", 620 | "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", 621 | "dev": true, 622 | "requires": { 623 | "randombytes": "^2.1.0" 624 | } 625 | }, 626 | "set-blocking": { 627 | "version": "2.0.0", 628 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", 629 | "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", 630 | "dev": true 631 | }, 632 | "sprintf-js": { 633 | "version": "1.0.3", 634 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 635 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 636 | "dev": true 637 | }, 638 | "string-width": { 639 | "version": "2.1.1", 640 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 641 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 642 | "dev": true, 643 | "requires": { 644 | "is-fullwidth-code-point": "^2.0.0", 645 | "strip-ansi": "^4.0.0" 646 | } 647 | }, 648 | "strip-ansi": { 649 | "version": "4.0.0", 650 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 651 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 652 | "dev": true, 653 | "requires": { 654 | "ansi-regex": "^3.0.0" 655 | } 656 | }, 657 | "strip-json-comments": { 658 | "version": "3.1.1", 659 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 660 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 661 | "dev": true 662 | }, 663 | "supports-color": { 664 | "version": "7.2.0", 665 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 666 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 667 | "dev": true, 668 | "requires": { 669 | "has-flag": "^4.0.0" 670 | } 671 | }, 672 | "to-regex-range": { 673 | "version": "5.0.1", 674 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 675 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 676 | "dev": true, 677 | "requires": { 678 | "is-number": "^7.0.0" 679 | } 680 | }, 681 | "type-detect": { 682 | "version": "4.0.8", 683 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", 684 | "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", 685 | "dev": true 686 | }, 687 | "which": { 688 | "version": "2.0.2", 689 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 690 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 691 | "dev": true, 692 | "requires": { 693 | "isexe": "^2.0.0" 694 | } 695 | }, 696 | "which-module": { 697 | "version": "2.0.0", 698 | "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", 699 | "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", 700 | "dev": true 701 | }, 702 | "wide-align": { 703 | "version": "1.1.3", 704 | "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", 705 | "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", 706 | "dev": true, 707 | "requires": { 708 | "string-width": "^1.0.2 || 2" 709 | } 710 | }, 711 | "workerpool": { 712 | "version": "6.0.2", 713 | "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.2.tgz", 714 | "integrity": "sha512-DSNyvOpFKrNusaaUwk+ej6cBj1bmhLcBfj80elGk+ZIo5JSkq+unB1dLKEOcNfJDZgjGICfhQ0Q5TbP0PvF4+Q==", 715 | "dev": true 716 | }, 717 | "wrap-ansi": { 718 | "version": "5.1.0", 719 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", 720 | "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", 721 | "dev": true, 722 | "requires": { 723 | "ansi-styles": "^3.2.0", 724 | "string-width": "^3.0.0", 725 | "strip-ansi": "^5.0.0" 726 | }, 727 | "dependencies": { 728 | "ansi-regex": { 729 | "version": "4.1.0", 730 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 731 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", 732 | "dev": true 733 | }, 734 | "ansi-styles": { 735 | "version": "3.2.1", 736 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 737 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 738 | "dev": true, 739 | "requires": { 740 | "color-convert": "^1.9.0" 741 | } 742 | }, 743 | "color-convert": { 744 | "version": "1.9.3", 745 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 746 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 747 | "dev": true, 748 | "requires": { 749 | "color-name": "1.1.3" 750 | } 751 | }, 752 | "color-name": { 753 | "version": "1.1.3", 754 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 755 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 756 | "dev": true 757 | }, 758 | "string-width": { 759 | "version": "3.1.0", 760 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 761 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 762 | "dev": true, 763 | "requires": { 764 | "emoji-regex": "^7.0.1", 765 | "is-fullwidth-code-point": "^2.0.0", 766 | "strip-ansi": "^5.1.0" 767 | } 768 | }, 769 | "strip-ansi": { 770 | "version": "5.2.0", 771 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 772 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 773 | "dev": true, 774 | "requires": { 775 | "ansi-regex": "^4.1.0" 776 | } 777 | } 778 | } 779 | }, 780 | "wrappy": { 781 | "version": "1.0.2", 782 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 783 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 784 | "dev": true 785 | }, 786 | "y18n": { 787 | "version": "4.0.1", 788 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", 789 | "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", 790 | "dev": true 791 | }, 792 | "yargs": { 793 | "version": "13.3.2", 794 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", 795 | "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", 796 | "dev": true, 797 | "requires": { 798 | "cliui": "^5.0.0", 799 | "find-up": "^3.0.0", 800 | "get-caller-file": "^2.0.1", 801 | "require-directory": "^2.1.1", 802 | "require-main-filename": "^2.0.0", 803 | "set-blocking": "^2.0.0", 804 | "string-width": "^3.0.0", 805 | "which-module": "^2.0.0", 806 | "y18n": "^4.0.0", 807 | "yargs-parser": "^13.1.2" 808 | }, 809 | "dependencies": { 810 | "ansi-regex": { 811 | "version": "4.1.0", 812 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 813 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", 814 | "dev": true 815 | }, 816 | "find-up": { 817 | "version": "3.0.0", 818 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", 819 | "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", 820 | "dev": true, 821 | "requires": { 822 | "locate-path": "^3.0.0" 823 | } 824 | }, 825 | "locate-path": { 826 | "version": "3.0.0", 827 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", 828 | "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", 829 | "dev": true, 830 | "requires": { 831 | "p-locate": "^3.0.0", 832 | "path-exists": "^3.0.0" 833 | } 834 | }, 835 | "p-limit": { 836 | "version": "2.3.0", 837 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", 838 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", 839 | "dev": true, 840 | "requires": { 841 | "p-try": "^2.0.0" 842 | } 843 | }, 844 | "p-locate": { 845 | "version": "3.0.0", 846 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", 847 | "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", 848 | "dev": true, 849 | "requires": { 850 | "p-limit": "^2.0.0" 851 | } 852 | }, 853 | "path-exists": { 854 | "version": "3.0.0", 855 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", 856 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", 857 | "dev": true 858 | }, 859 | "string-width": { 860 | "version": "3.1.0", 861 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 862 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 863 | "dev": true, 864 | "requires": { 865 | "emoji-regex": "^7.0.1", 866 | "is-fullwidth-code-point": "^2.0.0", 867 | "strip-ansi": "^5.1.0" 868 | } 869 | }, 870 | "strip-ansi": { 871 | "version": "5.2.0", 872 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 873 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 874 | "dev": true, 875 | "requires": { 876 | "ansi-regex": "^4.1.0" 877 | } 878 | } 879 | } 880 | }, 881 | "yargs-parser": { 882 | "version": "13.1.2", 883 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", 884 | "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", 885 | "dev": true, 886 | "requires": { 887 | "camelcase": "^5.0.0", 888 | "decamelize": "^1.2.0" 889 | } 890 | }, 891 | "yargs-unparser": { 892 | "version": "2.0.0", 893 | "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", 894 | "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", 895 | "dev": true, 896 | "requires": { 897 | "camelcase": "^6.0.0", 898 | "decamelize": "^4.0.0", 899 | "flat": "^5.0.2", 900 | "is-plain-obj": "^2.1.0" 901 | }, 902 | "dependencies": { 903 | "camelcase": { 904 | "version": "6.2.0", 905 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", 906 | "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", 907 | "dev": true 908 | }, 909 | "decamelize": { 910 | "version": "4.0.0", 911 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", 912 | "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", 913 | "dev": true 914 | } 915 | } 916 | }, 917 | "yocto-queue": { 918 | "version": "0.1.0", 919 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", 920 | "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", 921 | "dev": true 922 | } 923 | } 924 | } 925 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "imi-data-validator", 3 | "version": "1.0.0", 4 | "description": "IMIデータバリデーションコンポーネント", 5 | "main": "main.js", 6 | "files": [ 7 | "main.js", 8 | "lib", 9 | "bin", 10 | "example" 11 | ], 12 | "scripts": { 13 | "test": "mocha" 14 | }, 15 | "keywords": [ 16 | "imi" 17 | ], 18 | "author": "IMI Tool Project", 19 | "license": "MIT", 20 | "devDependencies": { 21 | "chai": "^4.2.0", 22 | "mocha": "^8.2.1" 23 | }, 24 | "dependencies": { 25 | "imi-moji-converter": "github:IMI-Tool-Project/imi-moji-converter", 26 | "imiv-parser": "^1.0.1" 27 | }, 28 | "repository": { 29 | "type": "git", 30 | "url": "git+https://github.com/IMI-Tool-Project/imi-data-validator.git" 31 | }, 32 | "bugs": { 33 | "url": "https://github.com/IMI-Tool-Project/imi-data-validator/issues" 34 | }, 35 | "homepage": "https://github.com/IMI-Tool-Project/imi-data-validator#readme" 36 | } 37 | -------------------------------------------------------------------------------- /test/test-charsets.js: -------------------------------------------------------------------------------- 1 | const charsets = require("../lib/charsets"); 2 | const expect = require('chai').expect; 3 | 4 | describe('imi-data-validator#charsets', () => { 5 | 6 | describe('数字 ISOIEC10646Annex-G-supplement-NUMERIC-compliant', () => { 7 | const uri = "https://imi.go.jp/CommonCharacterSets/ISOIEC10646Annex-G-supplement-NUMERIC-compliant"; 8 | it("定義", () => { 9 | expect(charsets[uri]).to.exist; 10 | }); 11 | const exp = new RegExp(`^${charsets[uri].moji}+$`); 12 | it("数字だけの文字列を valid と判定できること", () => { 13 | expect(exp.test("0123456789")).to.be.true; 14 | }); 15 | it("数字以外を含む文字列を invalid と判定できること", () => { 16 | expect(exp.test("0123456789a")).to.be.false; 17 | }); 18 | }); 19 | 20 | describe('カタカナ ISOIEC10646Annex-G-supplement-KATAKANA-compliant', () => { 21 | const uri = "https://imi.go.jp/CommonCharacterSets/ISOIEC10646Annex-G-supplement-KATAKANA-compliant"; 22 | it("定義", () => { 23 | expect(charsets[uri]).to.exist; 24 | }); 25 | const exp = new RegExp(`^${charsets[uri].moji}+$`); 26 | it("カタカナだけの文字列を valid と判定できること", () => { 27 | expect(exp.test("アイウエオカキケコ")).to.be.true; 28 | }); 29 | it("カタカナ以外を含む文字列を invalid と判定できること", () => { 30 | expect(exp.test("0123456789a")).to.be.false; 31 | }); 32 | }); 33 | 34 | describe('JISX0208 ISOIEC10646-CJK-JISX0208-1990-compliant', () => { 35 | const uri = "https://imi.go.jp/CommonCharacterSets/ISOIEC10646-CJK-JISX0208-1990-compliant"; 36 | it("定義", () => { 37 | expect(charsets[uri]).to.exist; 38 | }); 39 | const exp = new RegExp(`^${charsets[uri].moji}+$`); 40 | it("JISX0208だけの文字列を valid と判定できること", () => { 41 | expect(exp.test("山田太郎")).to.be.true; 42 | }); 43 | it("JISX0208以外を含む文字列を invalid と判定できること", () => { 44 | expect(exp.test("𩸽")).to.be.false; 45 | }); 46 | }); 47 | 48 | describe('JISX0212 ISOIEC10646-CJK-JISX0212-1990-compliant', () => { 49 | const uri = "https://imi.go.jp/CommonCharacterSets/ISOIEC10646-CJK-JISX0212-1990-compliant"; 50 | it("定義", () => { 51 | expect(charsets[uri]).to.exist; 52 | }); 53 | const exp = new RegExp(`^${charsets[uri].moji}+$`); 54 | it("JISX0212だけの文字列を valid と判定できること", () => { 55 | expect(exp.test("亖亗亝亯亹仃仐仚仛仠")).to.be.true; 56 | }); 57 | it("JISX0212以外を含む文字列を invalid と判定できること", () => { 58 | expect(exp.test("一亖亗亝亯亹仃仐仚仛仠")).to.be.false; 59 | expect(exp.test("𩸽亖亗亝亯亹仃仐仚仛仠")).to.be.false; 60 | expect(exp.test("0123456789亖亗亝亯亹仃仐仚仛仠")).to.be.false; 61 | expect(exp.test("アイウエオ亖亗亝亯亹仃仐仚仛仠")).to.be.false; 62 | }); 63 | }); 64 | 65 | describe('JISX0213 ISOIEC10646-CJK-JISX0213-2004-compliant', () => { 66 | const uri = "https://imi.go.jp/CommonCharacterSets/ISOIEC10646-CJK-JISX0213-2004-compliant"; 67 | it("定義", () => { 68 | expect(charsets[uri]).to.exist; 69 | }); 70 | const exp = new RegExp(`^(${charsets[uri].moji})+$`); 71 | it("JISX0213だけの文字列を valid と判定できること", () => { 72 | expect(exp.test("𩸽")).to.be.true; 73 | }); 74 | it("JISX0208以外を含む文字列を invalid と判定できること", () => { 75 | expect(exp.test("山田太郎")).to.be.false; 76 | }); 77 | }); 78 | }); 79 | -------------------------------------------------------------------------------- /test/test-main.js: -------------------------------------------------------------------------------- 1 | const generate = require("../main"); 2 | const expect = require('chai').expect; 3 | 4 | const trim_metadata = (src) => { 5 | if (typeof src === 'string') return src; 6 | if (Array.isArray(src)) 7 | return src.map(a => trim_metadata(a)); 8 | const dst = {}; 9 | Object.keys(src).filter(key => key !== "メタデータ").forEach(key => { 10 | dst[key] = trim_metadata(src[key]); 11 | }); 12 | return dst; 13 | }; 14 | 15 | const imi_core = require("fs").readFileSync(__dirname + "/imicore241.imiv.txt", "UTF-8"); 16 | const imi_hojin = ` 17 | #prefix ic: "http://imi.go.jp/ns/core/2#" 18 | #prefix hj: "http://example.org/" 19 | vocabulary "http://example.org/" ; 20 | 21 | property hj:法人番号 {@xsd:string} ; 22 | class hj:法人型 {@ic:法人型}; 23 | set hj:法人型>hj:法人番号; 24 | `; 25 | 26 | describe('imi-data-validator', () => { 27 | 28 | describe('基本構造', () => { 29 | 30 | const validate = generate(`${imi_core} 31 | #prefix ic: "http://imi.go.jp/ns/core/2#" 32 | datamodel; 33 | use ic:事物型>ic:表記{0..n}; 34 | `); 35 | 36 | describe('JSON-LD Context の付与', () => { 37 | it('@context がない場合は既定値を付与する', () => { 38 | expect(validate({ 39 | "@type": "事物型", 40 | "表記": "テスト" 41 | })["@context"]).deep.equal([ 42 | "https://imi.go.jp/ns/core/context.jsonld", 43 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 44 | ]); 45 | }); 46 | 47 | it('コアのみの場合は追加する', () => { 48 | expect(validate({ 49 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 50 | "@type": "事物型", 51 | "表記": "テスト" 52 | })["@context"]).deep.equal([ 53 | "https://imi.go.jp/ns/core/context.jsonld", 54 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 55 | ]); 56 | }); 57 | 58 | it('法人のみの場合は追加する', () => { 59 | expect(validate({ 60 | "@context": "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld", 61 | "@type": "事物型", 62 | "表記": "テスト" 63 | })["@context"]).deep.equal([ 64 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld", 65 | "https://imi.go.jp/ns/core/context.jsonld" 66 | ]); 67 | }); 68 | 69 | it('すでにそろっている場合には変更しない', () => { 70 | expect(validate({ 71 | "@context": [ 72 | "https://imi.go.jp/ns/core/context.jsonld", 73 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 74 | ], 75 | "@type": "事物型", 76 | "表記": "テスト" 77 | })["@context"]).deep.equal([ 78 | "https://imi.go.jp/ns/core/context.jsonld", 79 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 80 | ]); 81 | }); 82 | 83 | it('オブジェクト定義の場合は付与する', () => { 84 | expect(validate({ 85 | "@context": { 86 | "ex": "http://example.org" 87 | }, 88 | "@type": "事物型", 89 | "表記": "テスト" 90 | })["@context"]).deep.equal([{ 91 | "ex": "http://example.org" 92 | }, 93 | "https://imi.go.jp/ns/core/context.jsonld", 94 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 95 | ]); 96 | }); 97 | 98 | it('他の context.jsonld がある場合は足りないものを追記', () => { 99 | expect(validate({ 100 | "@context": "http://schema.org/", 101 | "@type": "事物型", 102 | "表記": "テスト" 103 | })["@context"]).deep.equal([ 104 | "http://schema.org/", 105 | "https://imi.go.jp/ns/core/context.jsonld", 106 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 107 | ]); 108 | }); 109 | }); 110 | 111 | describe('メタデータの付与', () => { 112 | it('ルートインスタンスに対する正常終了', () => { 113 | const input = { 114 | "@type": "事物型", 115 | "表記": "テスト" 116 | }; 117 | const result = validate(input); 118 | expect(result["メタデータ"]["種別"]).to.equal("INFO"); 119 | }); 120 | it('ルートインスタンスに対する警告', () => { 121 | const input = { 122 | "@type": "事物型", 123 | "表記": "テスト", 124 | "種別": "不要" 125 | }; 126 | const result = validate(input); 127 | expect(result["メタデータ"]).to.have.lengthOf(2); 128 | expect(result["メタデータ"][0]["種別"]).to.equal("WARNING"); 129 | expect(result["メタデータ"][1]["種別"]).to.equal("WARNING"); 130 | }); 131 | it('ルートインスタンスに対するエラー', () => { 132 | const input = { 133 | "@type": "場所型", 134 | "表記": "テスト" 135 | }; 136 | const result = validate(input); 137 | expect(result["メタデータ"]).to.have.lengthOf(2); 138 | expect(result["メタデータ"][0]["種別"]).to.equal("ERROR"); 139 | expect(result["メタデータ"][1]["種別"]).to.equal("ERROR"); 140 | }); 141 | it('graph 下のインスタンスに対する個別のメタデータ付与', () => { 142 | const input = { 143 | "@graph": [{ 144 | "@type": "事物型", 145 | "表記": "テスト" 146 | }, { 147 | "@type": "事物型", 148 | "表記": "テスト", 149 | "種別": "不要" 150 | }, { 151 | "@type": "場所型", 152 | "表記": "テスト" 153 | }] 154 | }; 155 | const result = validate(input); 156 | expect(result["@graph"][0]["メタデータ"]["種別"]).to.equal("INFO"); 157 | expect(result["@graph"][1]["メタデータ"]).to.have.lengthOf(2); 158 | expect(result["@graph"][1]["メタデータ"][0]["種別"]).to.equal("WARNING"); 159 | expect(result["@graph"][1]["メタデータ"][1]["種別"]).to.equal("WARNING"); 160 | expect(result["@graph"][2]["メタデータ"]).to.have.lengthOf(2); 161 | expect(result["@graph"][2]["メタデータ"][0]["種別"]).to.equal("ERROR"); 162 | expect(result["@graph"][2]["メタデータ"][1]["種別"]).to.equal("ERROR"); 163 | }); 164 | it('既存のメタデータは維持される', () => { 165 | const input = { 166 | "@type": "事物型", 167 | "表記": "テスト", 168 | "メタデータ": { 169 | "@type": "文書型", 170 | "種別": "最初から", 171 | "表記": "これは最初からあったものです" 172 | } 173 | }; 174 | const result = validate(input); 175 | 176 | console.log(JSON.stringify(result, null, 2)); 177 | expect(result["メタデータ"]).to.have.lengthOf(2); 178 | expect(result["メタデータ"][0]["種別"]).to.equal("最初から"); 179 | expect(result["メタデータ"][1]["種別"]).to.equal("INFO"); 180 | }); 181 | 182 | it('既存のメタデータは維持される2', () => { 183 | const input = { 184 | "@type": "事物型", 185 | "表記": "テスト", 186 | "種別": "DELETEME", 187 | "メタデータ": { 188 | "@type": "文書型", 189 | "種別": "最初から", 190 | "表記": "これは最初からあったものです" 191 | } 192 | }; 193 | const result = validate(input); 194 | 195 | console.log(JSON.stringify(result, null, 2)); 196 | expect(result["メタデータ"]).to.have.lengthOf(3); 197 | expect(result["メタデータ"][0]["種別"]).to.equal("最初から"); 198 | expect(result["メタデータ"][1]["種別"]).to.equal("WARNING"); 199 | expect(result["メタデータ"][2]["種別"]).to.equal("WARNING"); 200 | }); 201 | }); 202 | }); 203 | 204 | describe('データモデルの評価: 基本構造', () => { 205 | 206 | const validate = generate(`${imi_core} 207 | #prefix ic: "http://imi.go.jp/ns/core/2#" 208 | datamodel; 209 | use ic:場所型>ic:表記{1..1}; 210 | use ic:場所型>ic:地理座標{0..1}; 211 | use ic:場所型>ic:地理座標>ic:緯度{1..1}; 212 | use ic:場所型>ic:地理座標>ic:経度{1..1}; 213 | `); 214 | 215 | describe('プロパティの過不足', () => { 216 | 217 | 218 | it("充足している場合には INFO", () => { 219 | const input = { 220 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 221 | "@type": "場所型", 222 | "表記": "東京タワー", 223 | "地理座標": { 224 | "@type": "座標型", 225 | "緯度": "+35.6585805", 226 | "経度": "+139.7454329" 227 | } 228 | }; 229 | const expected = { 230 | "@context": [ 231 | "https://imi.go.jp/ns/core/context.jsonld", 232 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 233 | ], 234 | "@type": "場所型", 235 | "表記": "東京タワー", 236 | "地理座標": { 237 | "@type": "座標型", 238 | "緯度": "+35.6585805", 239 | "経度": "+139.7454329" 240 | } 241 | }; 242 | const result = validate(input); 243 | expect(result["メタデータ"]["種別"]).to.equal("INFO"); 244 | expect(trim_metadata(result)).deep.equal(expected); 245 | }); 246 | 247 | it("正常系に過剰なプロパティが付与された場合には削除して WARNING", () => { 248 | const input = { 249 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 250 | "@type": "場所型", 251 | "種別": "観光地", 252 | "表記": "東京タワー", 253 | "地理座標": { 254 | "@type": "座標型", 255 | "種別": "代表点", 256 | "緯度": "+35.6585805", 257 | "経度": "+139.7454329" 258 | } 259 | }; 260 | const expected = { 261 | "@context": [ 262 | "https://imi.go.jp/ns/core/context.jsonld", 263 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 264 | ], 265 | "@type": "場所型", 266 | "表記": "東京タワー", 267 | "地理座標": { 268 | "@type": "座標型", 269 | "緯度": "+35.6585805", 270 | "経度": "+139.7454329" 271 | } 272 | }; 273 | const result = validate(input); 274 | expect(result["メタデータ"]).to.have.lengthOf(2); 275 | expect(result["メタデータ"][0]["種別"]).to.equal("WARNING"); 276 | expect(result["メタデータ"][1]["種別"]).to.equal("WARNING"); 277 | expect(result["地理座標"]["メタデータ"]["種別"]).to.equal("WARNING"); 278 | expect(trim_metadata(result)).deep.equal(expected); 279 | }); 280 | 281 | it("必須プロパティが不足している場合には ERROR", () => { 282 | const input = { 283 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 284 | "@type": "場所型", 285 | "地理座標": { 286 | "@type": "座標型", 287 | "緯度": "+35.6585805" 288 | } 289 | }; 290 | const expected = { 291 | "@context": [ 292 | "https://imi.go.jp/ns/core/context.jsonld", 293 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 294 | ], 295 | "@type": "場所型", 296 | "地理座標": { 297 | "@type": "座標型", 298 | "緯度": "+35.6585805" 299 | } 300 | }; 301 | const result = validate(input); 302 | expect(result["メタデータ"]).to.have.lengthOf(2); 303 | expect(result["メタデータ"][0]["種別"]).to.equal("ERROR"); 304 | expect(result["メタデータ"][1]["種別"]).to.equal("ERROR"); 305 | expect(trim_metadata(result)).deep.equal(expected); 306 | }); 307 | 308 | }); 309 | 310 | describe("ルートクラスに対する評価", () => { 311 | 312 | it("インスタンスのルートに @type がない場合は補完して警告", () => { 313 | const input = { 314 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 315 | "表記": "東京タワー", 316 | "地理座標": { 317 | "@type": "座標型", 318 | "緯度": "+35.6585805", 319 | "経度": "+139.7454329" 320 | } 321 | }; 322 | const expected = { 323 | "@context": [ 324 | "https://imi.go.jp/ns/core/context.jsonld", 325 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 326 | ], 327 | "@type": "場所型", 328 | "表記": "東京タワー", 329 | "地理座標": { 330 | "@type": "座標型", 331 | "緯度": "+35.6585805", 332 | "経度": "+139.7454329" 333 | } 334 | }; 335 | const result = validate(input); 336 | expect(result["メタデータ"]).to.have.lengthOf(2); 337 | expect(result["メタデータ"][0]["種別"]).to.equal("WARNING"); 338 | expect(result["メタデータ"][1]["種別"]).to.equal("WARNING"); 339 | expect(trim_metadata(result)).deep.equal(expected); 340 | }); 341 | 342 | 343 | it("ルートクラスがデータモデルのクラスと一致しない場合はエラー", () => { 344 | const input = { 345 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 346 | "@type": "人型", 347 | "表記": "東京タワー", 348 | "地理座標": { 349 | "緯度": "+35.6585805", 350 | "経度": "+139.7454329" 351 | } 352 | }; 353 | const expected = { 354 | "@context": [ 355 | "https://imi.go.jp/ns/core/context.jsonld", 356 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 357 | ], 358 | "@type": "人型", 359 | "表記": "東京タワー", 360 | "地理座標": { 361 | "緯度": "+35.6585805", 362 | "経度": "+139.7454329" 363 | } 364 | }; 365 | const result = validate(input); 366 | expect(result["メタデータ"]).to.have.lengthOf(2); 367 | expect(result["メタデータ"][0]["種別"]).to.equal("ERROR"); 368 | expect(result["メタデータ"][1]["種別"]).to.equal("ERROR"); 369 | expect(trim_metadata(result)).deep.equal(expected); 370 | 371 | }); 372 | 373 | }); 374 | 375 | describe("中間のクラスに対する評価", () => { 376 | 377 | it("中間のクラスに @type がない場合に語彙定義から補完して警告", () => { 378 | const input = { 379 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 380 | "@type": "場所型", 381 | "表記": "東京タワー", 382 | "地理座標": { 383 | "緯度": "+35.6585805", 384 | "経度": "+139.7454329" 385 | } 386 | }; 387 | const expected = { 388 | "@context": [ 389 | "https://imi.go.jp/ns/core/context.jsonld", 390 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 391 | ], 392 | "@type": "場所型", 393 | "表記": "東京タワー", 394 | "地理座標": { 395 | "@type": "座標型", 396 | "緯度": "+35.6585805", 397 | "経度": "+139.7454329" 398 | } 399 | }; 400 | const result = validate(input); 401 | expect(result["地理座標"]["メタデータ"]["種別"]).to.equal("WARNING"); 402 | expect(result["メタデータ"]["種別"]).to.equal("WARNING"); 403 | expect(trim_metadata(result)).deep.equal(expected); 404 | }); 405 | 406 | it("中間のクラスに @type がない場合にデータモデル定義から補完して警告", () => { 407 | 408 | const validatePerson = generate(`${imi_core} 409 | #prefix ic: "http://imi.go.jp/ns/core/2#" 410 | datamodel; 411 | use ic:関与型>ic:関与者{1..1}{@ic:人型}; 412 | use ic:関与型>ic:関与者>ic:姓名{1..1}; 413 | `); 414 | 415 | const input = { 416 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 417 | "@type": "関与型", 418 | "関与者": { 419 | "姓名": "山田太郎" 420 | } 421 | }; 422 | const expected = { 423 | "@context": [ 424 | "https://imi.go.jp/ns/core/context.jsonld", 425 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 426 | ], 427 | "@type": "関与型", 428 | "関与者": { 429 | "@type": "人型", 430 | "姓名": "山田太郎" 431 | } 432 | }; 433 | const result = validatePerson(input); 434 | expect(result["メタデータ"]["種別"]).to.equal("WARNING"); 435 | expect(result["関与者"]["メタデータ"]["種別"]).to.equal("WARNING"); 436 | expect(trim_metadata(result)).deep.equal(expected); 437 | }); 438 | 439 | 440 | 441 | it("中間のクラスが語彙定義に反する場合はエラー", () => { 442 | const input = { 443 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 444 | "@type": "場所型", 445 | "表記": "東京タワー", 446 | "地理座標": { 447 | "@type": "数量型", 448 | "緯度": "+35.6585805", 449 | "経度": "+139.7454329" 450 | } 451 | }; 452 | const expected = { 453 | "@context": [ 454 | "https://imi.go.jp/ns/core/context.jsonld", 455 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 456 | ], 457 | "@type": "場所型", 458 | "表記": "東京タワー", 459 | "地理座標": { 460 | "@type": "数量型", 461 | "緯度": "+35.6585805", 462 | "経度": "+139.7454329" 463 | } 464 | }; 465 | const result = validate(input); 466 | expect(result["メタデータ"]["種別"]).to.equal("ERROR"); 467 | expect(result["地理座標"]["メタデータ"]["種別"]).to.equal("ERROR"); 468 | expect(trim_metadata(result)).deep.equal(expected); 469 | }); 470 | 471 | 472 | }); 473 | 474 | describe('複数のオブジェクト', () => { 475 | 476 | const datamodel = `${imi_core} 477 | #prefix ic: "http://imi.go.jp/ns/core/2#" 478 | datamodel; 479 | use ic:人型>ic:名称{1..n}; 480 | use ic:人型>ic:名称>ic:種別{1..1}; 481 | use ic:人型>ic:名称>ic:表記{1..1}; 482 | `; 483 | 484 | const validate = generate(datamodel); 485 | 486 | it("単独", () => { 487 | const input = { 488 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 489 | "@type": "人型", 490 | "名称": { 491 | "@type": "名称型", 492 | "種別": "本名", 493 | "表記": "ほんみょう" 494 | } 495 | }; 496 | const expected = { 497 | "@context": [ 498 | "https://imi.go.jp/ns/core/context.jsonld", 499 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 500 | ], 501 | "@type": "人型", 502 | "名称": { 503 | "@type": "名称型", 504 | "種別": "本名", 505 | "表記": "ほんみょう" 506 | } 507 | }; 508 | const result = validate(input); 509 | expect(result["メタデータ"]["種別"]).to.equal("INFO"); 510 | expect(trim_metadata(result)).deep.equal(expected); 511 | }); 512 | 513 | it("複数", () => { 514 | const input = { 515 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 516 | "@type": "人型", 517 | "名称": [{ 518 | "@type": "名称型", 519 | "種別": "本名", 520 | "表記": "ほんみょう" 521 | }, { 522 | "@type": "名称型", 523 | "種別": "ペンネーム", 524 | "表記": "ペンネーム" 525 | }] 526 | }; 527 | const expected = { 528 | "@context": [ 529 | "https://imi.go.jp/ns/core/context.jsonld", 530 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 531 | ], 532 | "@type": "人型", 533 | "名称": [{ 534 | "@type": "名称型", 535 | "種別": "本名", 536 | "表記": "ほんみょう" 537 | }, { 538 | "@type": "名称型", 539 | "種別": "ペンネーム", 540 | "表記": "ペンネーム" 541 | }] 542 | }; 543 | const result = validate(input); 544 | expect(result["メタデータ"]["種別"]).to.equal("INFO"); 545 | expect(trim_metadata(result)).deep.equal(expected); 546 | }); 547 | 548 | }); 549 | 550 | 551 | describe('複数のリテラル', () => { 552 | 553 | const datamodel = imi_core + ` 554 | #prefix ic: "http://imi.go.jp/ns/core/2#" 555 | datamodel; 556 | use ic:事物型>ic:種別{0..n}; 557 | `; 558 | 559 | const validate = generate(datamodel); 560 | 561 | it("単独", () => { 562 | const input = { 563 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 564 | "@type": "事物型", 565 | "種別": "INFO" 566 | }; 567 | const expected = { 568 | "@context": [ 569 | "https://imi.go.jp/ns/core/context.jsonld", 570 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 571 | ], 572 | "@type": "事物型", 573 | "種別": "INFO" 574 | }; 575 | const result = validate(input); 576 | expect(result["メタデータ"]["種別"]).to.equal("INFO"); 577 | expect(trim_metadata(result)).deep.equal(expected); 578 | }); 579 | 580 | it("複数", () => { 581 | const input = { 582 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 583 | "@type": "事物型", 584 | "種別": ["INFO", "WARNING", "ERROR"] 585 | }; 586 | const expected = { 587 | "@context": [ 588 | "https://imi.go.jp/ns/core/context.jsonld", 589 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 590 | ], 591 | "@type": "事物型", 592 | "種別": ["INFO", "WARNING", "ERROR"] 593 | }; 594 | const result = validate(input); 595 | expect(result["メタデータ"]["種別"]).to.equal("INFO"); 596 | expect(trim_metadata(result)).deep.equal(expected); 597 | }); 598 | 599 | }); 600 | 601 | describe('抽象クラスのインスタンスでの具体化', () => { 602 | 603 | const datamodel = imi_core + ` 604 | #prefix ic: "http://imi.go.jp/ns/core/2#" 605 | datamodel; 606 | use ic:関与型>ic:関与者{1..1}; 607 | use ic:関与型>ic:関与者>ic:表記{1..1}; 608 | `; 609 | 610 | const validate = generate(datamodel); 611 | 612 | it("定義", () => { 613 | const input = { 614 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 615 | "@type": "関与型", 616 | "関与者": { 617 | "@type": "実体型", 618 | "表記": "ロボット" 619 | } 620 | }; 621 | const expected = { 622 | "@context": [ 623 | "https://imi.go.jp/ns/core/context.jsonld", 624 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 625 | ], 626 | "@type": "関与型", 627 | "関与者": { 628 | "@type": "実体型", 629 | "表記": "ロボット" 630 | } 631 | }; 632 | const result = validate(input); 633 | expect(result["メタデータ"]["種別"]).to.equal("INFO"); 634 | expect(trim_metadata(result)).deep.equal(expected); 635 | }); 636 | it("補完", () => { 637 | const input = { 638 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 639 | "関与者": { 640 | "表記": "ロボット" 641 | } 642 | }; 643 | const expected = { 644 | "@context": [ 645 | "https://imi.go.jp/ns/core/context.jsonld", 646 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 647 | ], 648 | "@type": "関与型", 649 | "関与者": { 650 | "@type": "実体型", 651 | "表記": "ロボット" 652 | } 653 | }; 654 | const result = validate(input); 655 | expect(result["メタデータ"]).to.have.lengthOf(2); 656 | expect(result["メタデータ"][0]["種別"]).to.equal("WARNING"); 657 | expect(result["メタデータ"][1]["種別"]).to.equal("WARNING"); 658 | expect(result["関与者"]["メタデータ"]["種別"]).to.equal("WARNING"); 659 | expect(trim_metadata(result)).deep.equal(expected); 660 | }); 661 | 662 | it("サブクラス1", () => { 663 | const input = { 664 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 665 | "@type": "関与型", 666 | "関与者": { 667 | "@type": "法人型", 668 | "表記": "株式会社" 669 | } 670 | }; 671 | const expected = { 672 | "@context": [ 673 | "https://imi.go.jp/ns/core/context.jsonld", 674 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 675 | ], 676 | "@type": "関与型", 677 | "関与者": { 678 | "@type": "法人型", 679 | "表記": "株式会社" 680 | } 681 | }; 682 | const result = validate(input); 683 | expect(result["メタデータ"]["種別"]).to.equal("INFO"); 684 | expect(trim_metadata(result)).deep.equal(expected); 685 | }); 686 | 687 | it("サブクラス2", () => { 688 | const input = { 689 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 690 | "@type": "関与型", 691 | "関与者": { 692 | "@type": "人型", 693 | "表記": "ひと" 694 | } 695 | }; 696 | const expected = { 697 | "@context": [ 698 | "https://imi.go.jp/ns/core/context.jsonld", 699 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 700 | ], 701 | "@type": "関与型", 702 | "関与者": { 703 | "@type": "人型", 704 | "表記": "ひと" 705 | } 706 | }; 707 | const result = validate(input); 708 | expect(result["メタデータ"]["種別"]).to.equal("INFO"); 709 | expect(trim_metadata(result)).deep.equal(expected); 710 | }); 711 | 712 | }); 713 | 714 | describe('データモデルで指定された型制約の評価', () => { 715 | 716 | const datamodel = imi_core + imi_hojin + ` 717 | #prefix ic: "http://imi.go.jp/ns/core/2#" 718 | datamodel; 719 | use ic:関与型>ic:関与者>ic:表記{1..1}; 720 | use ic:関与型>ic:関与者{1..1}{@ic:法人型}; 721 | `; 722 | 723 | const validate = generate(datamodel); 724 | 725 | it("定義", () => { 726 | const input = { 727 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 728 | "@type": "関与型", 729 | "関与者": { 730 | "@type": "法人型", 731 | "表記": "ほうじん" 732 | } 733 | }; 734 | const expected = { 735 | "@context": [ 736 | "https://imi.go.jp/ns/core/context.jsonld", 737 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 738 | ], 739 | "@type": "関与型", 740 | "関与者": { 741 | "@type": "法人型", 742 | "表記": "ほうじん" 743 | } 744 | }; 745 | const result = validate(input); 746 | expect(result["メタデータ"]["種別"]).to.equal("INFO"); 747 | expect(trim_metadata(result)).deep.equal(expected); 748 | }); 749 | it("補完", () => { 750 | const input = { 751 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 752 | "関与者": { 753 | "表記": "ほうじん" 754 | } 755 | }; 756 | const expected = { 757 | "@context": [ 758 | "https://imi.go.jp/ns/core/context.jsonld", 759 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 760 | ], 761 | "@type": "関与型", 762 | "関与者": { 763 | "@type": "法人型", 764 | "表記": "ほうじん" 765 | } 766 | }; 767 | const result = validate(input); 768 | expect(result["メタデータ"]).to.have.lengthOf(2); 769 | expect(result["メタデータ"][0]["種別"]).to.equal("WARNING"); 770 | expect(result["メタデータ"][1]["種別"]).to.equal("WARNING"); 771 | expect(result["関与者"]["メタデータ"]["種別"]).to.equal("WARNING"); 772 | expect(trim_metadata(result)).deep.equal(expected); 773 | }); 774 | 775 | it("親クラス", () => { 776 | const input = { 777 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 778 | "@type": "関与型", 779 | "関与者": { 780 | "@type": "実体型", 781 | "表記": "エージェント" 782 | } 783 | }; 784 | const expected = { 785 | "@context": [ 786 | "https://imi.go.jp/ns/core/context.jsonld", 787 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 788 | ], 789 | "@type": "関与型", 790 | "関与者": { 791 | "@type": "実体型", 792 | "表記": "エージェント" 793 | } 794 | }; 795 | const result = validate(input); 796 | expect(result["メタデータ"]["種別"]).to.equal("ERROR"); 797 | expect(result["関与者"]["メタデータ"]["種別"]).to.equal("ERROR"); 798 | expect(trim_metadata(result)).deep.equal(expected); 799 | }); 800 | 801 | it("兄弟クラス", () => { 802 | const input = { 803 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 804 | "@type": "関与型", 805 | "関与者": { 806 | "@type": "人型", 807 | "表記": "ひと" 808 | } 809 | }; 810 | const expected = { 811 | "@context": [ 812 | "https://imi.go.jp/ns/core/context.jsonld", 813 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 814 | ], 815 | "@type": "関与型", 816 | "関与者": { 817 | "@type": "人型", 818 | "表記": "ひと" 819 | } 820 | }; 821 | const result = validate(input); 822 | expect(result["メタデータ"]["種別"]).to.equal("ERROR"); 823 | expect(result["関与者"]["メタデータ"]["種別"]).to.equal("ERROR"); 824 | expect(trim_metadata(result)).deep.equal(expected); 825 | }); 826 | 827 | it("サブクラス", () => { 828 | const input = { 829 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 830 | "@type": "関与型", 831 | "関与者": { 832 | "@type": "hj:法人型", 833 | "表記": "ほうじん" 834 | } 835 | }; 836 | const expected = { 837 | "@context": [ 838 | "https://imi.go.jp/ns/core/context.jsonld", 839 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 840 | ], 841 | "@type": "関与型", 842 | "関与者": { 843 | "@type": "hj:法人型", 844 | "表記": "ほうじん" 845 | } 846 | }; 847 | const result = validate(input); 848 | expect(result["メタデータ"]["種別"]).to.equal("INFO"); 849 | expect(trim_metadata(result)).deep.equal(expected); 850 | }); 851 | 852 | }); 853 | 854 | }); 855 | 856 | describe('カーディナリティ', () => { 857 | 858 | 859 | describe('カーディナリティ{1..1}', () => { 860 | 861 | const datamodel = imi_core + ` 862 | #prefix ic: "http://imi.go.jp/ns/core/2#" 863 | datamodel; 864 | use ic:ID型>ic:識別値{1..1}; 865 | `; 866 | 867 | const validate = generate(datamodel); 868 | 869 | it("充足の場合は INFO", () => { 870 | const input = { 871 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 872 | "@type": "ID型", 873 | "識別値": "1" 874 | }; 875 | const expected = { 876 | "@context": [ 877 | "https://imi.go.jp/ns/core/context.jsonld", 878 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 879 | ], 880 | "@type": "ID型", 881 | "識別値": "1" 882 | }; 883 | const result = validate(input); 884 | expect(result["メタデータ"]["種別"]).to.equal("INFO"); 885 | expect(trim_metadata(result)).deep.equal(expected); 886 | }); 887 | 888 | it("不足の場合は エラー", () => { 889 | const input = { 890 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 891 | "@type": "ID型" 892 | }; 893 | const result = validate(input); 894 | expect(result["メタデータ"]).to.have.lengthOf(2); 895 | expect(result["メタデータ"][0]["種別"]).to.equal("ERROR"); 896 | expect(result["メタデータ"][1]["種別"]).to.equal("ERROR"); 897 | }); 898 | 899 | it("過剰な場合はエラー", () => { 900 | const input = { 901 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 902 | "@type": "ID型", 903 | "識別値": ["1", "2", "3"] 904 | }; 905 | const result = validate(input); 906 | expect(result["メタデータ"]).to.have.lengthOf(2); 907 | expect(result["メタデータ"][0]["種別"]).to.equal("ERROR"); 908 | expect(result["メタデータ"][1]["種別"]).to.equal("ERROR"); 909 | }); 910 | 911 | }); 912 | 913 | 914 | }); 915 | 916 | describe('使用可能文字制約', () => { 917 | 918 | // 使用文字制約 919 | 920 | describe('文字制約:https://imi.go.jp/CommonCharacterSets/ISOIEC10646Annex-G-supplement-NUMERIC-compliant', () => { 921 | 922 | const datamodel = imi_core + ` 923 | #prefix ic: "http://imi.go.jp/ns/core/2#" 924 | datamodel; 925 | use ic:住所型>ic:郵便番号{1..n}{$"https://imi.go.jp/CommonCharacterSets/ISOIEC10646Annex-G-supplement-NUMERIC-compliant"}; 926 | `; 927 | 928 | const validate = generate(datamodel); 929 | 930 | it("充足", () => { 931 | const input = { 932 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 933 | "@type": "住所型", 934 | "郵便番号": "1234567" 935 | }; 936 | const expected = { 937 | "@context": [ 938 | "https://imi.go.jp/ns/core/context.jsonld", 939 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 940 | ], 941 | "@type": "住所型", 942 | "郵便番号": "1234567" 943 | }; 944 | const result = validate(input); 945 | expect(result["メタデータ"]["種別"]).to.equal("INFO"); 946 | expect(trim_metadata(result)).deep.equal(expected); 947 | }); 948 | 949 | it("逸脱", () => { 950 | const input = { 951 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 952 | "@type": "住所型", 953 | "郵便番号": "不明" 954 | }; 955 | const expected = { 956 | "@context": [ 957 | "https://imi.go.jp/ns/core/context.jsonld", 958 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 959 | ], 960 | "@type": "住所型", 961 | "郵便番号": "不明" 962 | }; 963 | const result = validate(input); 964 | expect(result["メタデータ"]).to.have.lengthOf(2); 965 | expect(result["メタデータ"][0]["種別"]).to.equal("ERROR"); 966 | expect(result["メタデータ"][1]["種別"]).to.equal("ERROR"); 967 | expect(trim_metadata(result)).deep.equal(expected); 968 | }); 969 | 970 | it("修復後の成功(全角数字から半角数字)", () => { 971 | const input = { 972 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 973 | "@type": "住所型", 974 | "郵便番号": "1234567" 975 | }; 976 | const expected = { 977 | "@context": [ 978 | "https://imi.go.jp/ns/core/context.jsonld", 979 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 980 | ], 981 | "@type": "住所型", 982 | "郵便番号": "1234567" 983 | }; 984 | const result = validate(input); 985 | expect(result["メタデータ"]).to.have.lengthOf(2); 986 | expect(result["メタデータ"][0]["種別"]).to.equal("WARNING"); 987 | expect(result["メタデータ"][1]["種別"]).to.equal("WARNING"); 988 | expect(trim_metadata(result)).deep.equal(expected); 989 | 990 | }); 991 | 992 | it("修復後の失敗(全角数字から半角数字)", () => { 993 | const input = { 994 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 995 | "@type": "住所型", 996 | "郵便番号": "123の4567" 997 | }; 998 | const expected = { 999 | "@context": [ 1000 | "https://imi.go.jp/ns/core/context.jsonld", 1001 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 1002 | ], 1003 | "@type": "住所型", 1004 | "郵便番号": "123の4567" 1005 | }; 1006 | const result = validate(input); 1007 | expect(result["メタデータ"]).to.have.lengthOf(2); 1008 | expect(result["メタデータ"][0]["種別"]).to.equal("ERROR"); 1009 | expect(result["メタデータ"][1]["種別"]).to.equal("ERROR"); 1010 | expect(trim_metadata(result)).deep.equal(expected); 1011 | }); 1012 | 1013 | it("複数", () => { 1014 | const input = { 1015 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 1016 | "@type": "住所型", 1017 | "郵便番号": ["9876543", "1234567"] 1018 | }; 1019 | const expected = { 1020 | "@context": [ 1021 | "https://imi.go.jp/ns/core/context.jsonld", 1022 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 1023 | ], 1024 | "@type": "住所型", 1025 | "郵便番号": ["9876543", "1234567"] 1026 | }; 1027 | const result = validate(input); 1028 | expect(result["メタデータ"]).to.have.lengthOf(3); 1029 | expect(result["メタデータ"][0]["種別"]).to.equal("WARNING"); 1030 | expect(result["メタデータ"][1]["種別"]).to.equal("WARNING"); 1031 | expect(result["メタデータ"][2]["種別"]).to.equal("WARNING"); 1032 | expect(trim_metadata(result)).deep.equal(expected); 1033 | }); 1034 | 1035 | }); 1036 | 1037 | describe('文字制約:https://imi.go.jp/CommonCharacterSets/ISOIEC10646Annex-G-supplement-KATAKANA-compliant', () => { 1038 | 1039 | const datamodel = imi_core + ` 1040 | #prefix ic: "http://imi.go.jp/ns/core/2#" 1041 | datamodel; 1042 | use ic:名称型>ic:カナ表記{1..n}{$"https://imi.go.jp/CommonCharacterSets/ISOIEC10646Annex-G-supplement-KATAKANA-compliant"}; 1043 | `; 1044 | 1045 | const validate = generate(datamodel); 1046 | 1047 | it("充足", () => { 1048 | const input = { 1049 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 1050 | "@type": "名称型", 1051 | "カナ表記": "プレミアムティーバッグ" 1052 | }; 1053 | const expected = { 1054 | "@context": [ 1055 | "https://imi.go.jp/ns/core/context.jsonld", 1056 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 1057 | ], 1058 | "@type": "名称型", 1059 | "カナ表記": "プレミアムティーバッグ" 1060 | }; 1061 | const result = validate(input); 1062 | expect(result["メタデータ"]["種別"]).to.equal("INFO"); 1063 | expect(trim_metadata(result)).deep.equal(expected); 1064 | }); 1065 | 1066 | it("逸脱", () => { 1067 | const input = { 1068 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 1069 | "@type": "名称型", 1070 | "カナ表記": "おーいお茶プレミアムティーバッグ" 1071 | }; 1072 | const expected = { 1073 | "@context": [ 1074 | "https://imi.go.jp/ns/core/context.jsonld", 1075 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 1076 | ], 1077 | "@type": "名称型", 1078 | "カナ表記": "おーいお茶プレミアムティーバッグ" 1079 | }; 1080 | const result = validate(input); 1081 | expect(result["メタデータ"]).to.have.lengthOf(2); 1082 | expect(result["メタデータ"][0]["種別"]).to.equal("ERROR"); 1083 | expect(result["メタデータ"][1]["種別"]).to.equal("ERROR"); 1084 | expect(trim_metadata(result)).deep.equal(expected); 1085 | }); 1086 | 1087 | it("修復後の成功(半角カナから全角カナ)", () => { 1088 | const input = { 1089 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 1090 | "@type": "名称型", 1091 | "カナ表記": "プレミアムティーバッグ" 1092 | }; 1093 | const expected = { 1094 | "@context": [ 1095 | "https://imi.go.jp/ns/core/context.jsonld", 1096 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 1097 | ], 1098 | "@type": "名称型", 1099 | "カナ表記": "プレミアムティーバッグ" 1100 | }; 1101 | const result = validate(input); 1102 | expect(result["メタデータ"]).to.have.lengthOf(2); 1103 | expect(result["メタデータ"][0]["種別"]).to.equal("WARNING"); 1104 | expect(result["メタデータ"][1]["種別"]).to.equal("WARNING"); 1105 | expect(trim_metadata(result)).deep.equal(expected); 1106 | }); 1107 | 1108 | it("修復後の失敗(半角カナから全角カナ)", () => { 1109 | const input = { 1110 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 1111 | "@type": "名称型", 1112 | "カナ表記": "おーいお茶プレミアムティーバッグ" 1113 | }; 1114 | const expected = { 1115 | "@context": [ 1116 | "https://imi.go.jp/ns/core/context.jsonld", 1117 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 1118 | ], 1119 | "@type": "名称型", 1120 | "カナ表記": "おーいお茶プレミアムティーバッグ" 1121 | }; 1122 | const result = validate(input); 1123 | expect(result["メタデータ"]).to.have.lengthOf(2); 1124 | expect(result["メタデータ"][0]["種別"]).to.equal("ERROR"); 1125 | expect(result["メタデータ"][1]["種別"]).to.equal("ERROR"); 1126 | expect(trim_metadata(result)).deep.equal(expected); 1127 | }); 1128 | 1129 | it("複数", () => { 1130 | const input = { 1131 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 1132 | "@type": "名称型", 1133 | "カナ表記": ["プレミアム", "ティーバッグ"] 1134 | }; 1135 | const expected = { 1136 | "@context": [ 1137 | "https://imi.go.jp/ns/core/context.jsonld", 1138 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 1139 | ], 1140 | "@type": "名称型", 1141 | "カナ表記": ["プレミアム", "ティーバッグ"] 1142 | }; 1143 | const result = validate(input); 1144 | expect(result["メタデータ"]).to.have.lengthOf(3); 1145 | expect(result["メタデータ"][0]["種別"]).to.equal("WARNING"); 1146 | expect(result["メタデータ"][1]["種別"]).to.equal("WARNING"); 1147 | expect(result["メタデータ"][2]["種別"]).to.equal("WARNING"); 1148 | expect(trim_metadata(result)).deep.equal(expected); 1149 | }); 1150 | 1151 | }); 1152 | 1153 | describe('文字制約:JIS第一第二水準のみを受容', () => { 1154 | 1155 | const datamodel = imi_core + ` 1156 | #prefix ic: "http://imi.go.jp/ns/core/2#" 1157 | datamodel; 1158 | use ic:事物型>ic:表記{1..n}{$"https://imi.go.jp/CommonCharacterSets/ISOIEC10646-CJK-JISX0208-1990-compliant"} ; 1159 | `; 1160 | 1161 | const validate = generate(datamodel); 1162 | 1163 | it("JIS第一第二水準のみ", () => { 1164 | const input = { 1165 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 1166 | "@type": "事物型", 1167 | "表記": "喜怒哀楽" 1168 | }; 1169 | const expected = { 1170 | "@context": [ 1171 | "https://imi.go.jp/ns/core/context.jsonld", 1172 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 1173 | ], 1174 | "@type": "事物型", 1175 | "表記": "喜怒哀楽" 1176 | }; 1177 | const result = validate(input); 1178 | expect(result["メタデータ"]["種別"]).to.equal("INFO"); 1179 | expect(trim_metadata(result)).deep.equal(expected); 1180 | }); 1181 | 1182 | it("JIS第三水準のみ", () => { 1183 | const input = { 1184 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 1185 | "@type": "事物型", 1186 | "表記": "㐂" 1187 | }; 1188 | const expected = { 1189 | "@context": [ 1190 | "https://imi.go.jp/ns/core/context.jsonld", 1191 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 1192 | ], 1193 | "@type": "事物型", 1194 | "表記": "㐂" 1195 | }; 1196 | const result = validate(input); 1197 | expect(result["メタデータ"]).to.have.lengthOf(2); 1198 | expect(result["メタデータ"][0]["種別"]).to.equal("ERROR"); 1199 | expect(result["メタデータ"][1]["種別"]).to.equal("ERROR"); 1200 | expect(trim_metadata(result)).deep.equal(expected); 1201 | }); 1202 | 1203 | it("混在", () => { 1204 | const input = { 1205 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 1206 | "@type": "事物型", 1207 | "表記": "㐂喜" 1208 | }; 1209 | const expected = { 1210 | "@context": [ 1211 | "https://imi.go.jp/ns/core/context.jsonld", 1212 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 1213 | ], 1214 | "@type": "事物型", 1215 | "表記": "㐂喜" 1216 | }; 1217 | const result = validate(input); 1218 | expect(result["メタデータ"]).to.have.lengthOf(2); 1219 | expect(result["メタデータ"][0]["種別"]).to.equal("ERROR"); 1220 | expect(result["メタデータ"][1]["種別"]).to.equal("ERROR"); 1221 | expect(trim_metadata(result)).deep.equal(expected); 1222 | }); 1223 | 1224 | }); 1225 | 1226 | 1227 | describe('文字制約:JIS第一第二水準のみを推奨、JIS第三第四は警告', () => { 1228 | 1229 | const datamodel = imi_core + ` 1230 | #prefix ic: "http://imi.go.jp/ns/core/2#" 1231 | datamodel; 1232 | use ic:事物型>ic:表記{1..n}{$"https://imi.go.jp/CommonCharacterSets/ISOIEC10646-CJK-JISX0208-1990-compliant| 1233 | [NotRecommended]https://imi.go.jp/CommonCharacterSets/ISOIEC10646-CJK-JISX0213-2004-compliant"} ; 1234 | `; 1235 | 1236 | const validate = generate(datamodel); 1237 | 1238 | it("JIS第一第二水準のみ", () => { 1239 | const input = { 1240 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 1241 | "@type": "事物型", 1242 | "表記": "喜" 1243 | }; 1244 | const expected = { 1245 | "@context": [ 1246 | "https://imi.go.jp/ns/core/context.jsonld", 1247 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 1248 | ], 1249 | "@type": "事物型", 1250 | "表記": "喜" 1251 | }; 1252 | const result = validate(input); 1253 | expect(result["メタデータ"]["種別"]).to.equal("INFO"); 1254 | expect(trim_metadata(result)).deep.equal(expected); 1255 | }); 1256 | 1257 | it("JIS第三水準のみ", () => { 1258 | 1259 | const input = { 1260 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 1261 | "@type": "事物型", 1262 | "表記": "㐂" 1263 | }; 1264 | const expected = { 1265 | "@context": [ 1266 | "https://imi.go.jp/ns/core/context.jsonld", 1267 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 1268 | ], 1269 | "@type": "事物型", 1270 | "表記": "㐂" 1271 | }; 1272 | const result = validate(input); 1273 | expect(result["メタデータ"]).to.have.lengthOf(2); 1274 | expect(result["メタデータ"][0]["種別"]).to.equal("WARNING"); 1275 | expect(result["メタデータ"][1]["種別"]).to.equal("WARNING"); 1276 | expect(trim_metadata(result)).deep.equal(expected); 1277 | }); 1278 | 1279 | it("混在", () => { 1280 | const input = { 1281 | "@context": "https://imi.go.jp/ns/core/context.jsonld", 1282 | "@type": "事物型", 1283 | "表記": "㐂喜" 1284 | }; 1285 | const expected = { 1286 | "@context": [ 1287 | "https://imi.go.jp/ns/core/context.jsonld", 1288 | "http://hojin-info.go.jp/ns/domain/biz/1/context.jsonld" 1289 | ], 1290 | "@type": "事物型", 1291 | "表記": "㐂喜" 1292 | }; 1293 | const result = validate(input); 1294 | expect(result["メタデータ"]).to.have.lengthOf(2); 1295 | expect(result["メタデータ"][0]["種別"]).to.equal("WARNING"); 1296 | expect(result["メタデータ"][1]["種別"]).to.equal("WARNING"); 1297 | expect(trim_metadata(result)).deep.equal(expected); 1298 | }); 1299 | 1300 | }); 1301 | 1302 | }); 1303 | 1304 | describe('グループ', () => { 1305 | 1306 | describe('グループ名と種別名が対応づくパターン', () => { 1307 | 1308 | const datamodel = imi_core + ` 1309 | #prefix ic: "http://imi.go.jp/ns/core/2#" 1310 | datamodel; 1311 | use ic:人型>ic:氏名[本名]{1..1}; 1312 | use ic:人型>ic:氏名[本名]>ic:姓名{1..1}; 1313 | use ic:人型>ic:氏名[本名]>ic:種別{1..1}{='本名'}; 1314 | use ic:人型>ic:氏名[ペンネーム]{0..n}; 1315 | use ic:人型>ic:氏名[ペンネーム]>ic:表記{1..1}; 1316 | use ic:人型>ic:氏名[ペンネーム]>ic:種別{1..1}{='ペンネーム'}; 1317 | `; 1318 | 1319 | const validate = generate(datamodel); 1320 | 1321 | it("本名のみ", () => { 1322 | const result = validate({ 1323 | "@type": "人型", 1324 | "氏名": { 1325 | "@type": "氏名型", 1326 | "種別": "本名", 1327 | "姓名": "夏目金之助" 1328 | } 1329 | }); 1330 | expect(result["メタデータ"]["種別"]).to.equal("INFO"); 1331 | }); 1332 | 1333 | it("両方ある", () => { 1334 | const result = validate({ 1335 | "@type": "人型", 1336 | "氏名": [{ 1337 | "@type": "氏名型", 1338 | "種別": "本名", 1339 | "姓名": "夏目金之助" 1340 | }, { 1341 | "@type": "氏名型", 1342 | "種別": "ペンネーム", 1343 | "表記": "夏目漱石" 1344 | }] 1345 | }); 1346 | expect(result["メタデータ"]["種別"]).to.equal("INFO"); 1347 | }); 1348 | 1349 | it("ペンネームが複数ある", () => { 1350 | const result = validate({ 1351 | "@type": "人型", 1352 | "氏名": [{ 1353 | "@type": "氏名型", 1354 | "種別": "本名", 1355 | "姓名": "夏目金之助" 1356 | }, { 1357 | "@type": "氏名型", 1358 | "種別": "ペンネーム", 1359 | "表記": "夏目漱石" 1360 | }, { 1361 | "@type": "氏名型", 1362 | "種別": "ペンネーム", 1363 | "表記": "なつめそうせき" 1364 | }] 1365 | }); 1366 | expect(result["メタデータ"]["種別"]).to.equal("INFO"); 1367 | }) 1368 | 1369 | it("本名がない", () => { 1370 | const result = validate({ 1371 | "@type": "人型", 1372 | "氏名": { 1373 | "@type": "氏名型", 1374 | "種別": "ペンネーム", 1375 | "表記": "夏目漱石" 1376 | } 1377 | }); 1378 | expect(result["メタデータ"]).to.have.lengthOf(2); 1379 | expect(result["メタデータ"][0]["種別"]).to.equal("ERROR"); 1380 | expect(result["メタデータ"][1]["種別"]).to.equal("ERROR"); 1381 | }); 1382 | 1383 | it("本名に姓名がない", () => { 1384 | const result = validate({ 1385 | "@type": "人型", 1386 | "氏名": { 1387 | "@type": "氏名型", 1388 | "種別": "本名", 1389 | "表記": "夏目漱石" 1390 | } 1391 | }); 1392 | expect(result["メタデータ"]["種別"]).to.equal("ERROR"); 1393 | expect(result["氏名"]["メタデータ"]).to.have.lengthOf(2); 1394 | expect(result["氏名"]["メタデータ"][0]["種別"]).to.equal("ERROR"); 1395 | expect(result["氏名"]["メタデータ"][1]["種別"]).to.equal("WARNING"); 1396 | }); 1397 | 1398 | }); 1399 | 1400 | }); 1401 | 1402 | describe('オプション', () => { 1403 | 1404 | describe('自動修復の無効化', () => { 1405 | const validate = generate(`${imi_core} 1406 | #prefix ic: "http://imi.go.jp/ns/core/2#" 1407 | datamodel; 1408 | use ic:住所型>ic:表記{0..1}; 1409 | use ic:住所型>ic:郵便番号{0..1}{$"https://imi.go.jp/CommonCharacterSets/ISOIEC10646Annex-G-supplement-NUMERIC-compliant"}; 1410 | use ic:住所型>ic:ビル名{0..1}{$"https://imi.go.jp/CommonCharacterSets/ISOIEC10646Annex-G-supplement-KATAKANA-compliant"}; 1411 | use ic:住所型>ic:種別コード{0..1}; 1412 | use ic:住所型>ic:種別コード>ic:表記{0..1}; 1413 | `, { 1414 | "disable_auto_fix": true 1415 | }); 1416 | 1417 | 1418 | it('ルートクラス名の省略がエラーになること', () => { 1419 | const result = validate({ 1420 | "表記": "テスト" 1421 | }); 1422 | expect(result["メタデータ"]).to.have.lengthOf(2); 1423 | expect(result["メタデータ"][0]["種別"]).to.equal("ERROR"); 1424 | expect(result["メタデータ"][1]["種別"]).to.equal("ERROR"); 1425 | }); 1426 | 1427 | it('下位クラスのクラス名省略がエラーになること', () => { 1428 | const result = validate({ 1429 | "@type": "住所型", 1430 | "表記": "テスト", 1431 | "種別コード": { 1432 | "表記": "本社住所" 1433 | } 1434 | }); 1435 | expect(result["メタデータ"]["種別"]).to.equal("ERROR"); 1436 | expect(result["種別コード"]["メタデータ"]["種別"]).to.equal("ERROR"); 1437 | }); 1438 | 1439 | it('全角数字の修復がおこなわれずエラーになること', () => { 1440 | const result = validate({ 1441 | "@type": "住所型", 1442 | "表記": "テスト", 1443 | "郵便番号": "1234567" 1444 | }); 1445 | expect(result["メタデータ"]).to.have.lengthOf(2); 1446 | expect(result["メタデータ"][0]["種別"]).to.equal("ERROR"); 1447 | expect(result["メタデータ"][1]["種別"]).to.equal("ERROR"); 1448 | expect(result["郵便番号"]).to.equal("1234567"); 1449 | }); 1450 | 1451 | it('半角カナの修復がおこなわれずエラーになること', () => { 1452 | const result = validate({ 1453 | "@type": "住所型", 1454 | "表記": "テスト", 1455 | "ビル名": "ロッポンギヒルズ" 1456 | }); 1457 | expect(result["メタデータ"]).to.have.lengthOf(2); 1458 | expect(result["メタデータ"][0]["種別"]).to.equal("ERROR"); 1459 | expect(result["メタデータ"][1]["種別"]).to.equal("ERROR"); 1460 | expect(result["ビル名"]).to.equal("ロッポンギヒルズ"); 1461 | }); 1462 | 1463 | }); 1464 | }); 1465 | 1466 | }); 1467 | -------------------------------------------------------------------------------- /test/test-util.js: -------------------------------------------------------------------------------- 1 | const Util = require("../lib/util"); 2 | const expect = require('chai').expect; 3 | 4 | describe('imi-data-validator#util', () => { 5 | 6 | describe('datatype', () => { 7 | describe('xsd:integer', () => { 8 | it('正常', () => { 9 | expect(Util.datatype("xsd:integer", "-256")).deep.equal({ 10 | "種別": "INFO" 11 | }); 12 | }); 13 | it('異常', () => { 14 | expect(Util.datatype("xsd:integer", "0256")).deep.equal({ 15 | "種別": "ERROR", 16 | "説明": "xsd:integer ではありません" 17 | }); 18 | }); 19 | }); 20 | describe('xsd:nonNegativeInteger', () => { 21 | it('正常', () => { 22 | expect(Util.datatype("xsd:nonNegativeInteger", "256")).deep.equal({ 23 | "種別": "INFO" 24 | }); 25 | }); 26 | it('異常', () => { 27 | expect(Util.datatype("xsd:nonNegativeInteger", "-256")).deep.equal({ 28 | "種別": "ERROR", 29 | "説明": "xsd:nonNegativeInteger ではありません" 30 | }); 31 | }); 32 | }); 33 | describe('xsd:date', () => { 34 | it('正常', () => { 35 | expect(Util.datatype("xsd:date", "2019-12-31")).deep.equal({ 36 | "種別": "INFO" 37 | }); 38 | }); 39 | it('異常', () => { 40 | expect(Util.datatype("xsd:date", "2019年12月31日")).deep.equal({ 41 | "種別": "ERROR", 42 | "説明": "xsd:date ではありません" 43 | }); 44 | }); 45 | }); 46 | }); 47 | 48 | describe('eq', () => { 49 | describe('文字列', () => { 50 | it('正常', () => { 51 | expect(Util.eq("Hello", "Hello")).deep.equal({ 52 | "種別": "INFO" 53 | }); 54 | }); 55 | it('異常', () => { 56 | expect(Util.eq("Hello", "World")).deep.equal({ 57 | "種別": "ERROR", 58 | "説明": "Hello でなければなりません" 59 | }); 60 | }); 61 | }); 62 | }); 63 | 64 | describe('lt', () => { 65 | describe('数値', () => { 66 | it('>', () => { 67 | expect(Util.lt("5", "4")).deep.equal({ 68 | "種別": "INFO" 69 | }); 70 | }); 71 | it('=', () => { 72 | expect(Util.lt("5", "5")).deep.equal({ 73 | "種別": "ERROR", 74 | "説明": "5 より小さくなければいけません" 75 | }); 76 | }); 77 | it('<', () => { 78 | expect(Util.lt("5", "6")).deep.equal({ 79 | "種別": "ERROR", 80 | "説明": "5 より小さくなければいけません" 81 | }); 82 | }); 83 | }); 84 | describe('非数値', () => { 85 | it('文字列', () => { 86 | expect(Util.lt("5", "world")).deep.equal({ 87 | "種別": "ERROR", 88 | "説明": "数値ではありません" 89 | }); 90 | }); 91 | }); 92 | }); 93 | 94 | describe('le', () => { 95 | describe('数値', () => { 96 | it('>', () => { 97 | expect(Util.le("5", "4")).deep.equal({ 98 | "種別": "INFO" 99 | }); 100 | }); 101 | it('=', () => { 102 | expect(Util.le("5", "5")).deep.equal({ 103 | "種別": "INFO" 104 | }); 105 | }); 106 | it('<', () => { 107 | expect(Util.le("5", "6")).deep.equal({ 108 | "種別": "ERROR", 109 | "説明": "5 以下でなければいけません" 110 | }); 111 | }); 112 | }); 113 | describe('非数値', () => { 114 | it('文字列', () => { 115 | expect(Util.le("5", "world")).deep.equal({ 116 | "種別": "ERROR", 117 | "説明": "数値ではありません" 118 | }); 119 | }); 120 | }); 121 | }); 122 | 123 | describe('gt', () => { 124 | describe('数値', () => { 125 | it('>', () => { 126 | expect(Util.gt("5", "4")).deep.equal({ 127 | "種別": "ERROR", 128 | "説明": "5 より大きくなければいけません" 129 | }); 130 | }); 131 | it('=', () => { 132 | expect(Util.gt("5", "5")).deep.equal({ 133 | "種別": "ERROR", 134 | "説明": "5 より大きくなければいけません" 135 | }); 136 | }); 137 | it('<', () => { 138 | expect(Util.gt("5", "6")).deep.equal({ 139 | "種別": "INFO" 140 | }); 141 | }); 142 | }); 143 | describe('非数値', () => { 144 | it('文字列', () => { 145 | expect(Util.gt("5", "world")).deep.equal({ 146 | "種別": "ERROR", 147 | "説明": "数値ではありません" 148 | }); 149 | }); 150 | }); 151 | }); 152 | 153 | describe('ge', () => { 154 | describe('数値', () => { 155 | it('>', () => { 156 | expect(Util.ge("5", "4")).deep.equal({ 157 | "種別": "ERROR", 158 | "説明": "5 以上でなければいけません" 159 | }); 160 | }); 161 | it('=', () => { 162 | expect(Util.ge("5", "5")).deep.equal({ 163 | "種別": "INFO" 164 | }); 165 | }); 166 | it('<', () => { 167 | expect(Util.ge("5", "6")).deep.equal({ 168 | "種別": "INFO" 169 | }); 170 | }); 171 | }); 172 | describe('非数値', () => { 173 | it('文字列', () => { 174 | expect(Util.ge("5", "world")).deep.equal({ 175 | "種別": "ERROR", 176 | "説明": "数値ではありません" 177 | }); 178 | }); 179 | }); 180 | }); 181 | 182 | describe('pattern', () => { 183 | it('正常', () => { 184 | expect(Util.pattern("^[0-9]{5}$", "01234")).deep.equal({ 185 | "種別": "INFO" 186 | }); 187 | }); 188 | it('失敗', () => { 189 | expect(Util.pattern("^[0-9]{5}$", "0123456789")).deep.equal({ 190 | "種別": "ERROR", 191 | "説明": "正規表現 ^[0-9]{5}$ に適合しません" 192 | }); 193 | }); 194 | }); 195 | 196 | describe('charsets', () => { 197 | const KATAKANA = "https://imi.go.jp/CommonCharacterSets/ISOIEC10646Annex-G-supplement-KATAKANA-compliant"; 198 | const NUMERIC = "https://imi.go.jp/CommonCharacterSets/ISOIEC10646Annex-G-supplement-NUMERIC-compliant"; 199 | 200 | describe('全角カナ', () => { 201 | const uri = KATAKANA; 202 | it("正常", () => { 203 | expect(Util.charset(uri, "アカサタナ")).deep.equal({ 204 | "種別": "INFO" 205 | }); 206 | }); 207 | it("異常", () => { 208 | expect(Util.charset(uri, "アカサタナはまやらわ")).deep.equal({ 209 | "種別": "ERROR", 210 | "説明": "[IMIユーティリティ文字セット-カナ(全角)] で規定されていない文字が使用されています" 211 | }); 212 | }); 213 | it("修復", () => { 214 | expect(Util.charset(uri, "アカサタナ")).deep.equal([{ 215 | "種別": "ERROR", 216 | "説明": "[IMIユーティリティ文字セット-カナ(全角)] で規定されていない文字が使用されています" 217 | }, { 218 | "種別": "WARNING", 219 | "説明": "[IMIユーティリティ文字セット-カナ(全角)] で規定されていない文字が使用されていましたが、半角カナ/全角カナ変換によって修正されました", 220 | "値": "アカサタナ" 221 | }]); 222 | }); 223 | }); 224 | describe('数字', () => { 225 | const uri = NUMERIC; 226 | it("正常", () => { 227 | expect(Util.charset(uri, "0123456789")).deep.equal({ 228 | "種別": "INFO" 229 | }); 230 | }); 231 | it("異常", () => { 232 | expect(Util.charset(uri, "アカサタナはまやらわ")).deep.equal({ 233 | "種別": "ERROR", 234 | "説明": "[IMIユーティリティ文字セット-数字] で規定されていない文字が使用されています" 235 | }); 236 | }); 237 | it("修復", () => { 238 | expect(Util.charset(uri, "0123456789")).deep.equal([{ 239 | "種別": "ERROR", 240 | "説明": "[IMIユーティリティ文字セット-数字] で規定されていない文字が使用されています" 241 | }, { 242 | "種別": "WARNING", 243 | "説明": "[IMIユーティリティ文字セット-数字] で規定されていない文字が使用されていましたが、全角数字/半角数字変換によって修正されました", 244 | "値": "0123456789" 245 | }]); 246 | }); 247 | }); 248 | describe('非推奨', () => { 249 | const uri = "[NotRecommended]" + KATAKANA; 250 | it("正常", () => { 251 | expect(Util.charset(uri, "01234")).deep.equal({ 252 | "種別": "INFO" 253 | }); 254 | }); 255 | it("非推奨のみ", () => { 256 | expect(Util.charset(uri, "アカサタナ")).deep.equal({ 257 | "種別": "WARNING", 258 | "説明": "[IMIユーティリティ文字セット-カナ(全角)] で規定された非推奨文字が使用されています" 259 | }); 260 | }); 261 | it("混在", () => { 262 | expect(Util.charset(uri, "01234アカサタナ")).deep.equal({ 263 | "種別": "WARNING", 264 | "説明": "[IMIユーティリティ文字セット-カナ(全角)] で規定された非推奨文字が使用されています" 265 | }); 266 | }); 267 | }); 268 | 269 | describe('推奨・非推奨混在', () => { 270 | const uri = NUMERIC + "|[NotRecommended]" + KATAKANA; 271 | it("推奨", () => { 272 | expect(Util.charset(uri, "01234")).deep.equal({ 273 | "種別": "INFO" 274 | }); 275 | }); 276 | it("非推奨", () => { 277 | expect(Util.charset(uri, "アカサタナ")).deep.equal({ 278 | "種別": "WARNING", 279 | "説明": "[IMIユーティリティ文字セット-カナ(全角)] で規定された非推奨文字が使用されています" 280 | }); 281 | }); 282 | it("推奨・非推奨", () => { 283 | expect(Util.charset(uri, "01234アカサタナ")).deep.equal({ 284 | "種別": "WARNING", 285 | "説明": "[IMIユーティリティ文字セット-カナ(全角)] で規定された非推奨文字が使用されています" 286 | }); 287 | }); 288 | it("推奨・禁止", () => { 289 | expect(Util.charset(uri, "01234abcde")).deep.equal({ 290 | "種別": "ERROR", 291 | "説明": "[IMIユーティリティ文字セット-数字,IMIユーティリティ文字セット-カナ(全角)] で規定されていない文字が使用されています" 292 | }); 293 | }); 294 | }); 295 | 296 | }); 297 | }); 298 | --------------------------------------------------------------------------------