@arpproject/vibearp-mcp 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,765 @@
1
+ // ******************************************************************************************
2
+ // Copyright (C) 2025-2026 SZTAKI, Department of Distributed Systems (https://dsd.sztaki.hu).
3
+ //
4
+ // SPDX-License-Identifier: Apache-2.0
5
+ // ******************************************************************************************
6
+ /**
7
+ * TypeScript conversion of CedarTemplateToDescriboProfileConverter.java
8
+ * Converts CEDAR templates to Describo profile format
9
+ */
10
+ // ============================================================================
11
+ // JsonHelper Utilities
12
+ // ============================================================================
13
+ /**
14
+ * Returns a JSON sub-element from the given JSON object and path
15
+ * @param json - a JSON object
16
+ * @param path - a JSON path, e.g. "a.b.c[2].d"
17
+ * @returns - a sub-element of json according to the given path, or null/undefined
18
+ */
19
+ function getJsonElement(json, path) {
20
+ const parts = path.split(/\.|\[|\]/);
21
+ let result = json;
22
+ for (const key of parts) {
23
+ const trimmedKey = key.trim();
24
+ if (trimmedKey === '') {
25
+ continue;
26
+ }
27
+ if (result == null) {
28
+ break;
29
+ }
30
+ if (Array.isArray(result)) {
31
+ const ix = parseInt(trimmedKey, 10);
32
+ result = result[ix];
33
+ }
34
+ else if (typeof result === 'object' && result !== null) {
35
+ result = result[trimmedKey];
36
+ }
37
+ else {
38
+ break;
39
+ }
40
+ }
41
+ return result;
42
+ }
43
+ /**
44
+ * Extract a string array from a JSON path
45
+ * @param json - a JSON object
46
+ * @param path - a JSON path
47
+ * @returns - array of strings, or empty array if not found
48
+ */
49
+ function getStringList(json, path) {
50
+ const jsonElement = getJsonElement(json, path);
51
+ if (jsonElement == null) {
52
+ return [];
53
+ }
54
+ if (Array.isArray(jsonElement)) {
55
+ return jsonElement;
56
+ }
57
+ return [];
58
+ }
59
+ /**
60
+ * Get a JSON object from a path
61
+ * @param json - a JSON object
62
+ * @param path - a JSON path
63
+ * @returns - JSON object or null
64
+ */
65
+ function getJsonObject(json, path) {
66
+ const jsonElement = getJsonElement(json, path);
67
+ if (jsonElement == null || typeof jsonElement !== 'object' || Array.isArray(jsonElement)) {
68
+ return null;
69
+ }
70
+ return jsonElement;
71
+ }
72
+ /**
73
+ * Get a JSON array from a path
74
+ * @param json - a JSON object
75
+ * @param path - a JSON path
76
+ * @returns - JSON array or null
77
+ */
78
+ function getJsonArray(json, path) {
79
+ const jsonElement = getJsonElement(json, path);
80
+ if (jsonElement == null || !Array.isArray(jsonElement)) {
81
+ return null;
82
+ }
83
+ return jsonElement;
84
+ }
85
+ /**
86
+ * Check if a JSON element exists at the given path
87
+ * @param json - a JSON object
88
+ * @param path - a JSON path
89
+ * @returns - true if element exists, false otherwise
90
+ */
91
+ function hasJsonElement(json, path) {
92
+ try {
93
+ return getJsonElement(json, path) != null;
94
+ }
95
+ catch (ex) {
96
+ return false;
97
+ }
98
+ }
99
+ // ============================================================================
100
+ // ArpService Methods (stubbed for external vocabulary)
101
+ // ============================================================================
102
+ /**
103
+ * Check if field has external vocabulary values
104
+ * @param cedarFieldTemplate - CEDAR field template
105
+ * @returns - always false (external vocab processing skipped)
106
+ */
107
+ function hasExternalValues(cedarFieldTemplate) {
108
+ return false;
109
+ }
110
+ /**
111
+ * Check if field is deprecated
112
+ * @param cedarFieldTemplate - CEDAR field template
113
+ * @returns - true if field is deprecated, false otherwise
114
+ */
115
+ function isDeprecatedField(cedarFieldTemplate) {
116
+ const deprecatedField = getJsonElement(cedarFieldTemplate, '_arp.dataverse.deprecated');
117
+ return deprecatedField != null && deprecatedField !== false && deprecatedField === true;
118
+ }
119
+ /**
120
+ * Get external vocabulary values
121
+ * @param cedarFieldTemplate - CEDAR field template
122
+ * @returns - always empty array (external vocab processing skipped)
123
+ */
124
+ function getExternalVocabValues(cedarFieldTemplate) {
125
+ return [];
126
+ }
127
+ // ============================================================================
128
+ // Inner Classes
129
+ // ============================================================================
130
+ /**
131
+ * DescriboInput class representing a single input field
132
+ */
133
+ class DescriboInput {
134
+ _id;
135
+ _name;
136
+ _label;
137
+ _help;
138
+ _type;
139
+ _values;
140
+ _required = false;
141
+ _multiple = false;
142
+ _minValue;
143
+ _maxValue;
144
+ _minLength;
145
+ _maxLength;
146
+ _regex;
147
+ _placeholder;
148
+ _numberType;
149
+ _dateFormat;
150
+ _style;
151
+ _deprecated = false;
152
+ constructor() { }
153
+ isDeprecated() {
154
+ return this._deprecated;
155
+ }
156
+ setDeprecated(deprecated) {
157
+ this._deprecated = deprecated;
158
+ }
159
+ getId() {
160
+ return this._id;
161
+ }
162
+ setId(id) {
163
+ this._id = id;
164
+ }
165
+ getName() {
166
+ return this._name;
167
+ }
168
+ setName(name) {
169
+ this._name = name;
170
+ }
171
+ getLabel() {
172
+ return this._label;
173
+ }
174
+ setLabel(label) {
175
+ this._label = label;
176
+ }
177
+ getHelp() {
178
+ return this._help;
179
+ }
180
+ setHelp(help) {
181
+ this._help = help;
182
+ }
183
+ getType() {
184
+ return this._type;
185
+ }
186
+ setType(type) {
187
+ this._type = type;
188
+ }
189
+ isRequired() {
190
+ return this._required;
191
+ }
192
+ setRequired(required) {
193
+ this._required = required;
194
+ }
195
+ isMultiple() {
196
+ return this._multiple;
197
+ }
198
+ setMultiple(multiple) {
199
+ this._multiple = multiple;
200
+ }
201
+ getValues() {
202
+ return this._values;
203
+ }
204
+ setValues(values) {
205
+ this._values = values;
206
+ }
207
+ getMinValue() {
208
+ return this._minValue;
209
+ }
210
+ setMinValue(minValue) {
211
+ this._minValue = minValue;
212
+ }
213
+ getMaxValue() {
214
+ return this._maxValue;
215
+ }
216
+ setMaxValue(maxValue) {
217
+ this._maxValue = maxValue;
218
+ }
219
+ getMinLength() {
220
+ return this._minLength;
221
+ }
222
+ setMinLength(minLength) {
223
+ this._minLength = minLength;
224
+ }
225
+ getMaxLength() {
226
+ return this._maxLength;
227
+ }
228
+ setMaxLength(maxLength) {
229
+ this._maxLength = maxLength;
230
+ }
231
+ getRegex() {
232
+ return this._regex;
233
+ }
234
+ setRegex(regex) {
235
+ this._regex = regex;
236
+ }
237
+ getPlaceholder() {
238
+ return this._placeholder;
239
+ }
240
+ setPlaceholder(placeholder) {
241
+ this._placeholder = placeholder;
242
+ }
243
+ getNumberType() {
244
+ return this._numberType;
245
+ }
246
+ setNumberType(numberType) {
247
+ this._numberType = numberType;
248
+ }
249
+ getDateFormat() {
250
+ return this._dateFormat;
251
+ }
252
+ setDateFormat(dateFormat) {
253
+ this._dateFormat = dateFormat;
254
+ }
255
+ getStyle() {
256
+ return this._style;
257
+ }
258
+ setStyle(style) {
259
+ this._style = style;
260
+ }
261
+ /**
262
+ * Convert DescriboInput to plain object for JSON serialization
263
+ */
264
+ toJSON() {
265
+ const obj = {};
266
+ if (this._id !== undefined)
267
+ obj.id = this._id;
268
+ if (this._name !== undefined)
269
+ obj.name = this._name;
270
+ if (this._label !== undefined)
271
+ obj.label = this._label;
272
+ if (this._help !== undefined)
273
+ obj.help = this._help;
274
+ if (this._type !== undefined)
275
+ obj.type = this._type;
276
+ if (this._values !== undefined)
277
+ obj.values = this._values;
278
+ // Always include boolean properties (even when false)
279
+ obj.required = this._required;
280
+ obj.multiple = this._multiple;
281
+ obj.deprecated = this._deprecated;
282
+ if (this._minValue !== undefined)
283
+ obj.minValue = this._minValue;
284
+ if (this._maxValue !== undefined)
285
+ obj.maxValue = this._maxValue;
286
+ if (this._minLength !== undefined)
287
+ obj.minLength = this._minLength;
288
+ if (this._maxLength !== undefined)
289
+ obj.maxLength = this._maxLength;
290
+ if (this._regex !== undefined)
291
+ obj.regex = this._regex;
292
+ if (this._placeholder !== undefined)
293
+ obj.placeholder = this._placeholder;
294
+ if (this._numberType !== undefined)
295
+ obj.numberType = this._numberType;
296
+ if (this._dateFormat !== undefined)
297
+ obj.dateFormat = this._dateFormat;
298
+ if (this._style !== undefined)
299
+ obj.style = this._style;
300
+ return obj;
301
+ }
302
+ }
303
+ /**
304
+ * ClassLocalization for storing label and help text
305
+ */
306
+ class ClassLocalization {
307
+ label;
308
+ help;
309
+ constructor(label, help) {
310
+ this.label = label;
311
+ this.help = help;
312
+ }
313
+ }
314
+ /**
315
+ * ProcessedDescriboProfileValues for storing intermediate processing results
316
+ */
317
+ class ProcessedDescriboProfileValues {
318
+ inputs = [];
319
+ classLocalizations = new Map();
320
+ constructor(inputs) {
321
+ this.inputs = inputs;
322
+ }
323
+ getInputs() {
324
+ return this.inputs;
325
+ }
326
+ setInputs(inputs) {
327
+ this.inputs = inputs;
328
+ }
329
+ }
330
+ // ============================================================================
331
+ // Main Converter Class
332
+ // ============================================================================
333
+ export class CedarTemplateToDescriboProfileConverter {
334
+ language;
335
+ cedarDescriboFieldTypes;
336
+ cedarDescriboNumberTypes;
337
+ cedarDescriboDateTypes;
338
+ constructor(language) {
339
+ this.language = language ?? 'en';
340
+ // Initialize field type mappings
341
+ this.cedarDescriboFieldTypes = new Map([
342
+ ['textfield', ['Text']],
343
+ ['temporal', ['Date']],
344
+ ['numeric', ['Number']],
345
+ ['richtext', ['TextArea']],
346
+ ['textarea', ['TextArea']],
347
+ ['link', ['URL']],
348
+ ['list', ['Select']],
349
+ ['radio', ['Select']],
350
+ ['phone-number', ['Text']],
351
+ ['email', ['Text']],
352
+ ['checkbox', ['Select']] // Checkbox is mapped to Select
353
+ ]);
354
+ this.cedarDescriboNumberTypes = new Map([
355
+ ['xsd:decimal', ['Any']],
356
+ ['xsd:long', ['Long']],
357
+ ['xsd:int', ['Int']],
358
+ ['xsd:double', ['Double']],
359
+ ['xsd:float', ['Float']]
360
+ ]);
361
+ this.cedarDescriboDateTypes = new Map([
362
+ ['xsd:dateTime', ['DateTime']],
363
+ ['xsd:date', ['Date']],
364
+ ['xsd:time', ['Time']]
365
+ ]);
366
+ }
367
+ /**
368
+ * Main conversion method - converts CEDAR template to Describo profile
369
+ * @param cedarTemplate - CEDAR template as JSON string
370
+ * @returns - Describo profile as JSON string
371
+ */
372
+ processCedarTemplate(cedarTemplate) {
373
+ const describoProfileTemplate = {
374
+ metadata: {
375
+ name: 'Cedar to Describo generated profile',
376
+ version: 1.0,
377
+ description: 'Generated Describo schema from a Cedar template',
378
+ warnMissingProperty: true
379
+ },
380
+ classes: {
381
+ Dataset: {
382
+ definition: 'override',
383
+ subClassOf: [],
384
+ inputs: []
385
+ }
386
+ },
387
+ enabledClasses: ['Dataset']
388
+ };
389
+ const classTemplate = {
390
+ definition: 'override',
391
+ subClassOf: [],
392
+ inputs: []
393
+ };
394
+ const describoProfile = JSON.parse(JSON.stringify(describoProfileTemplate));
395
+ const cedarTemplateJson = JSON.parse(cedarTemplate);
396
+ this.processProfileMetadata(cedarTemplateJson, describoProfile);
397
+ const profValues = this.processTemplate(cedarTemplateJson, new ProcessedDescriboProfileValues([]), 'Dataset');
398
+ // Add default values for builtin types
399
+ if (this.language === 'hu') {
400
+ profValues.classLocalizations.set('Dataset', new ClassLocalization('Adatcsomag', 'Fájlok és metaadataik adatcsomagja'));
401
+ profValues.classLocalizations.set('File', new ClassLocalization('Fájl', 'Adatfájl'));
402
+ profValues.classLocalizations.set('Text', new ClassLocalization('Szöveg', 'Szöveg'));
403
+ profValues.classLocalizations.set('Number', new ClassLocalization('Szám', 'Szám'));
404
+ profValues.classLocalizations.set('Select', new ClassLocalization('Kiválasztás', 'Kiválasztás'));
405
+ profValues.classLocalizations.set('TextArea', new ClassLocalization('Hosszú szöveg', 'Hosszú szöveg'));
406
+ profValues.classLocalizations.set('Date', new ClassLocalization('Dátum', 'Dátum'));
407
+ }
408
+ else {
409
+ profValues.classLocalizations.set('Dataset', new ClassLocalization('Dataset', 'A collection of files with metadata'));
410
+ profValues.classLocalizations.set('File', new ClassLocalization('File', 'Data file'));
411
+ }
412
+ const classes = describoProfile.classes;
413
+ for (const input of profValues.inputs) {
414
+ const isDeprecated = input[1].isDeprecated();
415
+ if (!isDeprecated) {
416
+ const allChildrenAreDeprecated = this.areAllChildrenDeprecated(input, profValues.inputs);
417
+ if (!allChildrenAreDeprecated) {
418
+ const className = input[0];
419
+ if (!classes[className]) {
420
+ classes[className] = JSON.parse(JSON.stringify(classTemplate));
421
+ }
422
+ const classJson = classes[className];
423
+ classJson.inputs.push(input[1].toJSON());
424
+ const classLoc = profValues.classLocalizations.get(className);
425
+ if (classLoc != null) {
426
+ // This is our custom localisation at class level
427
+ classJson.label = classLoc.label;
428
+ classJson.help = classLoc.help;
429
+ }
430
+ }
431
+ }
432
+ }
433
+ // This is the Describo supported way of localisation
434
+ const localisation = {};
435
+ profValues.classLocalizations.forEach((value, key) => {
436
+ localisation[key] = value.label;
437
+ });
438
+ describoProfile.localisation = localisation;
439
+ const enabledClassesSet = new Set();
440
+ profValues.inputs
441
+ .filter(pair => !pair[1].isDeprecated())
442
+ .forEach(pair => enabledClassesSet.add(pair[0]));
443
+ describoProfile.enabledClasses = Array.from(enabledClassesSet);
444
+ return JSON.stringify(describoProfile, null, 2);
445
+ }
446
+ /**
447
+ * Check if all children of an input are deprecated
448
+ */
449
+ areAllChildrenDeprecated(input, inputs) {
450
+ if (input[0] === 'Dataset') {
451
+ const typeName = input[1].getName();
452
+ if (!typeName) {
453
+ return false;
454
+ }
455
+ const filtered = inputs.filter(pair => pair[0] === typeName);
456
+ return filtered.length > 0 && filtered.every(pair => pair[1].isDeprecated());
457
+ }
458
+ else {
459
+ return false;
460
+ }
461
+ }
462
+ /**
463
+ * Process template properties recursively
464
+ */
465
+ processTemplate(cedarTemplate, processedDescriboProfileValues, parentName) {
466
+ const propertyNames = getStringList(cedarTemplate, '_ui.order');
467
+ for (const propertyName of propertyNames) {
468
+ // Note: cannot use getJsonObject here because the propertyName may contain ".", eg:
469
+ // coverage.Spectral.CentralWavelength, which would result in properties.coverage.Spectral.CentralWavelength
470
+ const properties = cedarTemplate.properties;
471
+ if (!properties || !properties[propertyName]) {
472
+ continue;
473
+ }
474
+ const property = properties[propertyName];
475
+ const propertyType = property['@type'] ?? null;
476
+ // richtext type can not be used in Describo, leave it out from the profile
477
+ const inputType = getJsonElement(property, '_ui.inputType');
478
+ if (inputType && typeof inputType === 'string' && inputType === 'richtext') {
479
+ continue;
480
+ }
481
+ const contextProps = getJsonElement(cedarTemplate, 'properties.@context.properties');
482
+ if (!contextProps || !contextProps[propertyName] || !contextProps[propertyName].enum || !Array.isArray(contextProps[propertyName].enum) || contextProps[propertyName].enum.length === 0) {
483
+ continue;
484
+ }
485
+ const inputId = contextProps[propertyName].enum[0];
486
+ if (propertyType != null) {
487
+ const actPropertyType = typeof propertyType === 'string' ? propertyType.substring(propertyType.lastIndexOf('/') + 1) : null;
488
+ if (!actPropertyType) {
489
+ continue;
490
+ }
491
+ const ui = property._ui;
492
+ const isHidden = ui && ui.hidden === true;
493
+ if (!isHidden && (actPropertyType === 'TemplateField' || actPropertyType === 'StaticTemplateField')) {
494
+ const valueConstraints = property._valueConstraints;
495
+ const allowMultiple = (valueConstraints && valueConstraints.multipleChoice === true) ||
496
+ (property.minItems !== undefined || property.maxItems !== undefined);
497
+ this.processTemplateField(property, allowMultiple, inputId, processedDescriboProfileValues, parentName);
498
+ }
499
+ else if (actPropertyType === 'TemplateElement') {
500
+ const propertyLabels = getJsonObject(cedarTemplate, '_ui.propertyLabels');
501
+ this.processTemplateElement(property, processedDescriboProfileValues, false, inputId, parentName, propertyLabels);
502
+ }
503
+ }
504
+ else {
505
+ const actPropertyType = property.type;
506
+ if (actPropertyType === 'array') {
507
+ const propertyLabels = getJsonObject(cedarTemplate, '_ui.propertyLabels');
508
+ this.processArray(property, processedDescriboProfileValues, inputId, parentName, propertyLabels);
509
+ }
510
+ }
511
+ }
512
+ return processedDescriboProfileValues;
513
+ }
514
+ /**
515
+ * Process a template field
516
+ */
517
+ processTemplateField(templateField, allowMultiple, inputId, processedDescriboProfileValues, parentName) {
518
+ const describoInput = new DescriboInput();
519
+ let fieldType = null;
520
+ const inputTypeElement = getJsonElement(templateField, '_ui.inputType');
521
+ if (inputTypeElement && typeof inputTypeElement === 'string') {
522
+ fieldType = inputTypeElement;
523
+ }
524
+ const externalVocab = hasExternalValues(templateField);
525
+ if (externalVocab) {
526
+ fieldType = 'list';
527
+ }
528
+ describoInput.setId(inputId);
529
+ // Replace the ":" with "." upon generating the Describo Profile from the CEDAR Template
530
+ const schemaName = templateField['schema:name'];
531
+ if (!schemaName || typeof schemaName !== 'string') {
532
+ return; // Skip if no schema name
533
+ }
534
+ describoInput.setName(schemaName.replace(':', '.'));
535
+ const label = this.getLocalizedLabel(templateField);
536
+ describoInput.setLabel(label);
537
+ const help = this.getLocalizedHelp(templateField);
538
+ describoInput.setHelp(help);
539
+ describoInput.setType(this.getDescriboType(fieldType));
540
+ // Special Select styles for checkbox and radio CEDAR types
541
+ if (fieldType === 'checkbox') {
542
+ describoInput.setStyle('checkbox');
543
+ }
544
+ else if (fieldType === 'radio') {
545
+ describoInput.setStyle('radio');
546
+ }
547
+ const requiredValue = getJsonElement(templateField, '_valueConstraints.requiredValue');
548
+ describoInput.setRequired(requiredValue === true);
549
+ const minValue = getJsonElement(templateField, '_valueConstraints.minValue');
550
+ describoInput.setMinValue(minValue != null && typeof minValue === 'number' ? Math.floor(minValue) : undefined);
551
+ const maxValue = getJsonElement(templateField, '_valueConstraints.maxValue');
552
+ describoInput.setMaxValue(maxValue != null && typeof maxValue === 'number' ? Math.floor(maxValue) : undefined);
553
+ const minLength = getJsonElement(templateField, '_valueConstraints.minLength');
554
+ describoInput.setMinLength(minLength != null && typeof minLength === 'number' ? Math.floor(minLength) : undefined);
555
+ const maxLength = getJsonElement(templateField, '_valueConstraints.maxLength');
556
+ describoInput.setMaxLength(maxLength != null && typeof maxLength === 'number' ? Math.floor(maxLength) : undefined);
557
+ const regex = getJsonElement(templateField, '_valueConstraints.regex');
558
+ describoInput.setRegex(regex != null && typeof regex === 'string' ? regex : undefined);
559
+ const placeholder = getJsonElement(templateField, '_arp.dataverse.watermark');
560
+ describoInput.setPlaceholder(placeholder != null && typeof placeholder === 'string' ? placeholder : undefined);
561
+ describoInput.setMultiple(allowMultiple);
562
+ describoInput.setDeprecated(isDeprecatedField(templateField));
563
+ let literalValues = [];
564
+ if (fieldType != null && (fieldType === 'list' || fieldType === 'radio' || fieldType === 'checkbox')) {
565
+ if (externalVocab) {
566
+ literalValues = getExternalVocabValues(templateField);
567
+ if (literalValues.length > 0) {
568
+ describoInput.setValues(literalValues);
569
+ }
570
+ }
571
+ else {
572
+ const jsonElement = getJsonElement(templateField, '_valueConstraints.literals');
573
+ const literals = jsonElement != null && Array.isArray(jsonElement) ? jsonElement : [];
574
+ literalValues = [];
575
+ literals.forEach((literal) => {
576
+ if (literal && typeof literal === 'object' && literal.label && typeof literal.label === 'string') {
577
+ literalValues.push(literal.label);
578
+ }
579
+ });
580
+ }
581
+ if (literalValues.length > 0) {
582
+ describoInput.setValues(literalValues);
583
+ }
584
+ }
585
+ if (fieldType === 'numeric') {
586
+ // minValue and maxValue always handled as an int, even for long, double and float numbers
587
+ const numMinValue = getJsonElement(templateField, '_valueConstraints.minValue');
588
+ describoInput.setMinValue(numMinValue != null && typeof numMinValue === 'number' ? Math.floor(numMinValue) : undefined);
589
+ const numMaxValue = getJsonElement(templateField, '_valueConstraints.maxValue');
590
+ describoInput.setMaxValue(numMaxValue != null && typeof numMaxValue === 'number' ? Math.floor(numMaxValue) : undefined);
591
+ const numberType = getJsonElement(templateField, '_valueConstraints.numberType');
592
+ if (numberType != null && typeof numberType === 'string') {
593
+ const cedarNumberType = this.cedarDescriboNumberTypes.get(numberType);
594
+ if (cedarNumberType) {
595
+ describoInput.setNumberType(cedarNumberType);
596
+ }
597
+ }
598
+ }
599
+ if (fieldType === 'temporal') {
600
+ const temporalType = getJsonElement(templateField, '_valueConstraints.temporalType');
601
+ if (temporalType != null && typeof temporalType === 'string') {
602
+ const cedarDateType = this.cedarDescriboDateTypes.get(temporalType);
603
+ if (cedarDateType) {
604
+ describoInput.setType(cedarDateType);
605
+ }
606
+ }
607
+ }
608
+ // hard-coded regexes
609
+ if (fieldType === 'email' && describoInput.getRegex() == null) {
610
+ describoInput.setRegex('^((?!\\.)[\\w\\-_.]*[^.])(@\\w+(\\-?\\w+)*)(\\.\\w+(\\-?\\w+)*)*\\.[a-zA-Z]{2,}$');
611
+ }
612
+ if (fieldType === 'phone-number' && describoInput.getRegex() == null) {
613
+ describoInput.setRegex('(?:([+]\\d{1,4})[-.\\s]?)?(?:[(](\\d{1,3})[)][-.\\s]?)?(\\d{1,4})[-.\\s]?(\\d{1,4})[-.\\s]?(\\d{1,9})');
614
+ }
615
+ if (fieldType === 'textfield') {
616
+ const dateFormat = getJsonElement(templateField, '_arp.aroma.dateFormat');
617
+ if (dateFormat != null && typeof dateFormat === 'string') {
618
+ describoInput.setDateFormat([dateFormat]);
619
+ }
620
+ }
621
+ processedDescriboProfileValues.inputs.push([parentName, describoInput]);
622
+ }
623
+ /**
624
+ * "dataverseFile" is a special Template Element in CEDAR that is used to represent file relations
625
+ * this property needs to be handled differently
626
+ */
627
+ processTemplateElement(templateElement, processedDescriboProfileValues, allowMultiple, inputId, parentName, propertyLabels) {
628
+ const describoInput = new DescriboInput();
629
+ const schemaName = templateElement['schema:name'];
630
+ if (!schemaName || typeof schemaName !== 'string') {
631
+ return; // Skip if no schema name
632
+ }
633
+ const elementNameReplaced = schemaName.replace(':', '.');
634
+ // Replace the ":" with "." upon generating the Describo Profile from the CEDAR Template
635
+ const schemaIdentifier = templateElement['schema:identifier'];
636
+ const type = schemaIdentifier && typeof schemaIdentifier === 'string' ? schemaIdentifier.replace(':', '.') : elementNameReplaced;
637
+ const actualType = type === 'dataverseFile' ? 'File' : type === 'dataverseDataset' ? 'Dataset' : elementNameReplaced;
638
+ describoInput.setId(inputId);
639
+ describoInput.setName(elementNameReplaced);
640
+ const label = this.getLocalizedLabel(templateElement);
641
+ describoInput.setLabel(label);
642
+ const help = this.getLocalizedHelp(templateElement);
643
+ describoInput.setHelp(help);
644
+ describoInput.setType([actualType]);
645
+ const requiredValue = getJsonElement(templateElement, '_valueConstraints.requiredValue');
646
+ describoInput.setRequired(requiredValue === true);
647
+ const allowsMultiple = allowMultiple || templateElement.minItems !== undefined || templateElement.maxItems !== undefined;
648
+ describoInput.setMultiple(allowsMultiple);
649
+ describoInput.setDeprecated(isDeprecatedField(templateElement));
650
+ processedDescriboProfileValues.classLocalizations.set(elementNameReplaced, new ClassLocalization(label, help ?? ''));
651
+ processedDescriboProfileValues.inputs.push([parentName, describoInput]);
652
+ this.processTemplate(templateElement, processedDescriboProfileValues, elementNameReplaced);
653
+ }
654
+ /**
655
+ * Process array type
656
+ */
657
+ processArray(array, processedDescriboProfileValues, inputId, parentName, propertyLabels) {
658
+ const items = array.items;
659
+ if (!items) {
660
+ return;
661
+ }
662
+ const inputType = getJsonElement(items, '_ui.inputType');
663
+ if (inputType != null && typeof inputType === 'string') {
664
+ this.processTemplateField(items, true, inputId, processedDescriboProfileValues, parentName);
665
+ }
666
+ else {
667
+ this.processTemplateElement(items, processedDescriboProfileValues, true, inputId, parentName, propertyLabels);
668
+ }
669
+ }
670
+ /**
671
+ * Process profile metadata
672
+ */
673
+ processProfileMetadata(cedarTemplate, describoProfile) {
674
+ let name = cedarTemplate['schema:name'];
675
+ if (!name || typeof name !== 'string') {
676
+ name = 'Untitled';
677
+ }
678
+ if (this.language === 'hu') {
679
+ const hunName = cedarTemplate.hunName;
680
+ if (hunName && typeof hunName === 'string') {
681
+ name = hunName;
682
+ }
683
+ }
684
+ describoProfile.metadata.name = name;
685
+ let desc = cedarTemplate['schema:description'];
686
+ if (!desc || typeof desc !== 'string') {
687
+ desc = '';
688
+ }
689
+ if (this.language === 'hu') {
690
+ const hunDescription = cedarTemplate.hunDescription;
691
+ if (hunDescription && typeof hunDescription === 'string') {
692
+ desc = hunDescription;
693
+ }
694
+ }
695
+ describoProfile.metadata.description = desc;
696
+ }
697
+ getDescriboType(arg) {
698
+ if (arg == null) {
699
+ return undefined;
700
+ }
701
+ // If it's an object, treat it as templateField
702
+ if (typeof arg === 'object') {
703
+ const fieldType = getJsonElement(arg, '_ui.inputType');
704
+ if (fieldType != null && typeof fieldType === 'string' && this.cedarDescriboFieldTypes.has(fieldType)) {
705
+ return this.cedarDescriboFieldTypes.get(fieldType);
706
+ }
707
+ return undefined;
708
+ }
709
+ // If it's a string, treat it as cedarFieldType
710
+ if (typeof arg === 'string') {
711
+ return this.cedarDescriboFieldTypes.get(arg);
712
+ }
713
+ return undefined;
714
+ }
715
+ /**
716
+ * Get localized label
717
+ */
718
+ getLocalizedLabel(obj) {
719
+ let label = '';
720
+ let engLabel = obj['schema:name'];
721
+ if (!engLabel || typeof engLabel !== 'string') {
722
+ engLabel = '';
723
+ }
724
+ // Absolute fallback: the field name
725
+ const prefLabel = obj['skos:prefLabel'];
726
+ // If we have an english name in skos:prefLabel, use that
727
+ if (prefLabel != null && typeof prefLabel === 'string' && prefLabel.length > 0) {
728
+ engLabel = prefLabel;
729
+ }
730
+ // If we have an hunLabel, use that for hunLabel, otherwise fall back to engLabel
731
+ if (this.language === 'hu') {
732
+ const hunLabel = obj.hunLabel;
733
+ if (hunLabel == null || typeof hunLabel !== 'string' || hunLabel.length === 0) {
734
+ label = engLabel + ' (magyarul)';
735
+ }
736
+ else {
737
+ label = hunLabel;
738
+ }
739
+ }
740
+ else {
741
+ label = engLabel;
742
+ }
743
+ return label;
744
+ }
745
+ /**
746
+ * Get localized help text
747
+ */
748
+ getLocalizedHelp(obj) {
749
+ let help = undefined;
750
+ if (this.language === 'hu') {
751
+ const hunDescription = obj.hunDescription;
752
+ if (hunDescription != null && typeof hunDescription === 'string') {
753
+ help = hunDescription;
754
+ }
755
+ }
756
+ else {
757
+ const schemaDescription = obj['schema:description'];
758
+ if (schemaDescription != null && typeof schemaDescription === 'string') {
759
+ help = schemaDescription;
760
+ }
761
+ }
762
+ return help;
763
+ }
764
+ }
765
+ //# sourceMappingURL=cedar-converter.js.map