{"version":3,"file":"RDFconverter.mjs","sources":["../../../lib/data-provider-interface/utils/RDFconverter.js"],"sourcesContent":["import N3 from \"n3\";\nimport { isEmpty } from \"lodash\";\nimport { has } from \"lodash\";\n\nimport generalDpiConfig from \"../config/dpi-spec-config\";\n\nimport generalHelper from \"./general-helper\";\n\n/**\n * Converts all properties for given data from form input data into RDF (N-Triples)\n * @param {Object} data Data given within an object. Data stored as follows { datasets: {...}, distributions: [{...},...], catalogues: {...}}\n * @param {String} property Name of property which should be converted (either 'datasets' or 'catalogues')\n * @returns String of converted data in RDF format (N-Triples)\n */\nfunction convertToRDF(data, property, specification) {\n  let finishedRDFdata;\n\n  let dpiConfig = specification;\n\n  // writer for adding data as quads\n  const RDFdata = new N3.Writer({\n    prefixes: dpiConfig.prefixes,\n    format: \"N-Triples\",\n  });\n  // datasetURI also needed for distribution creation (add distributionURI to dataset (dcat:distribution))\n  const datasetURI = `https://piveau.eu/set/data/${data.datasets.datasetID}`;\n\n  // convert values for datasets/catalogues\n  convertPropertyValues(\n    RDFdata,\n    data[property],\n    property,\n    \"\",\n    \"\",\n    true,\n    datasetURI,\n    dpiConfig\n  ); // datasets and catalogues\n\n  // include distribution data into same graph\n  // differentiation neccessary because datasets also include distributions\n  if (property === \"datasets\") {\n    // multiple distributions possible -> [{data of distribution 1}, {data of distribution 2}, ...]\n    for (let index = 0; index < data.distributions.length; index += 1) {\n      convertPropertyValues(\n        RDFdata,\n        data.distributions[index],\n        \"distributions\",\n        \"\",\n        \"\",\n        true,\n        datasetURI,\n        dpiConfig\n      );\n    }\n  }\n\n  RDFdata.end((error, result) => (finishedRDFdata = result));\n  return finishedRDFdata;\n}\n\n/**\n * Converts each single value of given form data based on type into RDF\n * @param {N3.Writer} RDFdataset Dataset the converted RDF data should be added to\n * @param {Object} data Object containing data as key-value pairs\n * @param {String} property String determining which property is handled (datasets/distributions/catalogues)\n * @param {DataFactory} preMainURI (can be undefined) Could be a namedNode or BlankNode containing an URI\n * @param {DataFactory} preMainType (can be undefined) NamedNode determining the type of the current property (e.g. dcat:Dataset (as object))\n * @param {Boolean} setMain Value determining if additional values should be set (type, id, sample...)\n * @param {String} datasetURI URI of dataset for use in distribution conversion\n */\nfunction convertPropertyValues(\n  RDFdataset,\n  data,\n  property,\n  preMainURI,\n  preMainType,\n  setMain,\n  datasetURI,\n  dpiConfig\n) {\n  const formatTypes = dpiConfig.formatTypes;\n\n  // method can be called recursively for nested properties\n  // need to access id of parent node for later use as subject -> provide via method parameters (preMainURI & preMainType)\n  let mainURI;\n  let mainType;\n\n  // parent method can be called recursively for nested values\n  // if called on non-nested values a overall id and type muste be set (setMain -> true)\n  if (setMain) {\n    if (property === \"datasets\") {\n      mainType = generalHelper.addNamespace(\"dcat:Dataset\", dpiConfig);\n      mainURI = N3.DataFactory.namedNode(datasetURI); // datasetID should never be empty because of frontend checking\n    } else if (property === \"catalogues\") {\n      mainType = generalHelper.addNamespace(\"dcat:Catalog\", dpiConfig);\n      mainURI = N3.DataFactory.namedNode(\n        `https://piveau.eu/set/data/${data.datasetID}`\n      ); // datasetID should never be empty because of frontend checking\n    } else {\n      mainType = generalHelper.addNamespace(\"dcat:Distribution\", dpiConfig);\n      const randomId = generalHelper.makeId(10);\n      // distribution id can be random, will be overwritten by backend on saving data\n      mainURI = N3.DataFactory.namedNode(\n        `https://piveau.eu/set/data/${randomId}`\n      );\n    }\n\n    // parent method can be called recursively to convert nested values\n    // but setting the overal type and id of a dataset/catalogue is only required once at the beginning\n    // -> only set additional properties when setMain === true\n    setAdditionalProperties(\n      RDFdataset,\n      data,\n      mainURI,\n      mainType,\n      property,\n      datasetURI,\n      dpiConfig\n    );\n  } else {\n    // called on nested properties with already given URI and type which should used in the following conversion process\n    mainURI = preMainURI;\n    mainType = preMainType;\n  }\n\n  // distributions may have download URLs, if no downloadURL is provided -> provided accessUrls will be also set as downloadUrls\n  // accessUrl is a required property and therefore always provided (made sure by the frontend)\n  // const downloadUrlsProvided = has(data, 'dcat:downloadURL') && !isEmpty(data['dcat:downloadURL']) && data['dcat:downloadURL'].map(el => !isEmpty(el['@id'])).reduce((a, b) => b);\n\n  // loop trough all keys within data object and convert values (or nested values) to RDF\n  const valueKeys = Object.keys(data);\n  for (let index = 0; index < valueKeys.length; index += 1) {\n    const key = valueKeys[index]; // key format: either a normal name for special properties (e.g. datasetID) or namespaced keys (e.g. dct:title)\n\n    if (generalHelper.propertyHasValue(data[key])) {\n      // all properties are sorted by their format (see .../data-provider-interface/config/format-types.js)\n      // depending on the format the corresponding conversion-method is used, writing the result to the overall RDF-writer\n      if (formatTypes.singularString[property].includes(key)) {\n        convertSingularString(RDFdataset, mainURI, data, key, dpiConfig);\n      } else if (formatTypes.singularURI[property].includes(key)) {\n        convertSingularURI(RDFdataset, mainURI, data, key, dpiConfig);\n      } else if (formatTypes.multipleURI[property].includes(key)) {\n        // if no dowloadURL is provided, set accessUrls as downloadUrls\n        // if (!downloadUrlsProvided && key === 'dcat:accessURL') {\n        //     // copy accessurl array to donwloadurl array and convert data\n\n        //     data['dcat:downloadURL'] = cloneDeep(data['dcat:accessURL']);\n        //     convertMultipleURI(RDFdataset, mainURI, data, 'dcat:downloadURL', property, dpiConfig);\n        // }\n\n        convertMultipleURI(RDFdataset, mainURI, data, key, property, dpiConfig);\n      } else if (formatTypes.typedStrings[property].includes(key)) {\n        convertTypedString(RDFdataset, mainURI, data, key, dpiConfig);\n      } else if (formatTypes.multilingualStrings[property].includes(key)) {\n        convertMultilingual(RDFdataset, mainURI, data, key, dpiConfig);\n      } else if (formatTypes.groupedProperties[property].includes(key)) {\n        // grouped properties are properties provided by the form which consist of multiple properties (e.g contactPoint)\n        // the properties values are stored within an object located within an array\n        // for repeatable properties there are multiple objects in this array, otherwise there is just one\n\n        let actualData;\n        // vcard:hasAdress is an object as well as dct:creator and skos:notation\n        if (\n          key === \"vcard:hasAddress\" ||\n          key === \"dct:creator\" ||\n          key === \"skos:notation\" ||\n          key === \"spdx:checksum\" \n        )\n          actualData = [data[key]];\n        else actualData = data[key];\n\n        // looping trough all existing objects within the array\n        for (let groupId = 0; groupId < actualData.length; groupId += 1) {\n          let currentGroupData = actualData[groupId];        \n          if (!isEmpty(currentGroupData)) {\n            if (key === \"skos:notation\") {\n              // property skos:notation work a little bit different then other properties\n              // the form provides a value and a type from two seperated fields ({'@value': '...', '@type': '...'})\n              // the resulting RDF should merge these values into a typed literal (value^^type)\n              if (\n                has(currentGroupData, \"@value\") &&\n                !isEmpty(currentGroupData[\"@value\"])\n              ) {\n                let notationValue;\n\n                // if a type is given, use to form typed literal\n                // if no type is given, only use value to create literal\n                if (\n                  has(currentGroupData, \"@type\") &&\n                  !isEmpty(currentGroupData[\"@type\"])\n                ) {\n                  // typed literal\n                  notationValue = N3.DataFactory.literal(\n                    currentGroupData[\"@value\"],\n                    N3.DataFactory.namedNode(currentGroupData[\"@type\"].resource)\n                  );\n                } else {\n                  // literal\n                  notationValue = N3.DataFactory.literal(\n                    currentGroupData[\"@value\"]\n                  );\n                }\n\n                // add type for adms:identifier\n                RDFdataset.addQuad(\n                  N3.DataFactory.quad(\n                    mainURI,\n                    N3.DataFactory.namedNode(\n                      generalHelper.addNamespace(\"rdf:type\", dpiConfig)\n                    ),\n                    N3.DataFactory.namedNode(\n                      generalHelper.addNamespace(\"adms:Identifier\", dpiConfig)\n                    )\n                  )\n                );\n\n                // save quadruple with typed or untyped literal\n                RDFdataset.addQuad(\n                  N3.DataFactory.quad(\n                    mainURI,\n                    N3.DataFactory.namedNode(\n                      generalHelper.addNamespace(key, dpiConfig)\n                    ),\n                    notationValue\n                  )\n                );\n\n                // resulting rdf quads should look like this:\n                // datasetId  adms:identifier  admsIdentifierUtl\n                //  admsIdentifierUrl  rdf:type  adms:Identifier\n                //  admsIdentifierUrl  skos:notation  value^^type\n              }\n            } else {\n              let groupBlankNode;\n\n              // because grouped properties have a list of nested properties we need an initial quadruple stating the parent property\n              // using a blank node as object which later serves as subject for the nested properties\n              // RDF example:\n              // datasetID  dct:contactPoint  blankNodeId\n              //   blankNodeId foaf:mbox  email@exmaple.com\n              //   blankNodeId  fn:name  InsitutionName ...\n\n              // some form fields provide an URL which should serves as namedNode for other nested values (e.g. conformsTo)\n              // RDF example:\n              // datasetID  dct:conformsTo  conformsToURI\n              //  conformsToURI  dct:title  conformsTitle\n\n              if (\n                (key === \"foaf:page\" ||\n                  key === \"adms:identifier\" ||\n                  key === \"dct:conformsTo\") &&\n                has(currentGroupData, \"@id\")\n              ) {\n                groupBlankNode = N3.DataFactory.namedNode(\n                  currentGroupData[\"@id\"]\n                );\n              }\n           \n              // all properties that don't provide an URL serving as namedNode for nested values need to define a blank node\n\n              // page gets type but also has multilingual fields with preseleted langauge\n              // don't create blank node if there is not data for page beside the preselected language\n              let emptyPage = false;\n\n              if (key === \"foaf:page\") {\n                // if page has title and/or description property given, check if there are values given\n                const hasTitle = has(currentGroupData, \"dct:title\");\n                const hasDescription = has(currentGroupData, \"dct:description\");\n\n                let hasNoValueKeysTitle = true;\n                let hasEmptyValueTitle = true;\n                let hasNoValueKeysDescription = true;\n                let hasEmptyValueDescription = true;\n\n                if (hasTitle) {\n                  hasNoValueKeysTitle = !currentGroupData[\"dct:title\"].every(\n                    (el) => has(el, \"@value\")\n                  );\n                  hasEmptyValueTitle = currentGroupData[\"dct:title\"].every(\n                    (el) => isEmpty(el[\"@value\"])\n                  );\n                }\n\n                if (hasDescription) {\n                  hasNoValueKeysDescription = !currentGroupData[\n                    \"dct:description\"\n                  ].every((el) => has(el, \"@value\"));\n                  hasEmptyValueDescription = currentGroupData[\n                    \"dct:description\"\n                  ].every((el) => isEmpty(el[\"@value\"]));\n                }\n\n                // page should be handled as empty if:\n                // no title and/or no description given\n                // if properties given: no value given or value empty\n                if (\n                  (hasNoValueKeysTitle || hasEmptyValueTitle) &&\n                  (hasNoValueKeysDescription || hasEmptyValueDescription)\n                )\n                  emptyPage = true;\n              }\n\n              if (!emptyPage) {\n                if (!groupBlankNode)\n                  groupBlankNode = N3.DataFactory.blankNode(\"\");\n\n                // save inital quadruple using the named or blank node as object\n                // e.g.  datasetId  dct:contactPoint  blankNode/namedNode\n                RDFdataset.addQuad(\n                  N3.DataFactory.quad(\n                    mainURI,\n                    N3.DataFactory.namedNode(\n                      generalHelper.addNamespace(key, dpiConfig)\n                    ),\n                    groupBlankNode\n                  )\n                );\n\n                // some properties provide additional types\n                if (has(formatTypes.additionalPropertyTypes, key)) {\n                  RDFdataset.addQuad(\n                    N3.DataFactory.quad(\n                      groupBlankNode,\n                      N3.DataFactory.namedNode(\n                        generalHelper.addNamespace(\"rdf:type\", dpiConfig)\n                      ),\n                      N3.DataFactory.namedNode(\n                        generalHelper.addNamespace(\n                          formatTypes.additionalPropertyTypes[key],\n                          dpiConfig\n                        )\n                      )\n                    )\n                  );\n                }\n\n                // temporal values nested inside another object: \"dct:temporal\": [{ \"dct:temporal\": { \"dcat:startDate\": \"...\", \"dcat:endDate\": \"...\" } }]\n                if (key === \"dct:temporal\") {\n                  if (has(currentGroupData, \"dct:temporal\")) {\n                    currentGroupData = currentGroupData[\"dct:temporal\"];\n                  }\n                }\n\n                // convert all nested values provided by form\n                convertPropertyValues(\n                  RDFdataset,\n                  currentGroupData,\n                  property,\n                  groupBlankNode,\n                  mainType,\n                  false,\n                  dpiConfig,\n                  dpiConfig\n                );\n              }\n            }\n          }\n        }\n      } else if (formatTypes.conditionalProperties[property].includes(key)) {\n        // publisher either is an URI or a group with multiple values (name, homepage, email)\n        // license either is an URI or a group with multiple values ()\n        if (key === \"dct:publisher\" || key === \"dct:license\") {\n          // data contains either {resource: '...', name: '...'} or object containing other keys\n          if (has(data[key], \"resource\")) {\n            convertSingularURI(RDFdataset, mainURI, data, key, dpiConfig);\n          } else {\n            const groupBlankNode = N3.DataFactory.blankNode(\"\");\n\n            // some properties provide additional types\n            if (has(formatTypes.additionalPropertyTypes, key)) {\n              RDFdataset.addQuad(\n                N3.DataFactory.quad(\n                  groupBlankNode,\n                  N3.DataFactory.namedNode(\n                    generalHelper.addNamespace(\"rdf:type\", dpiConfig)\n                  ),\n                  N3.DataFactory.namedNode(\n                    generalHelper.addNamespace(\n                      formatTypes.additionalPropertyTypes[key],\n                      dpiConfig\n                    )\n                  )\n                )\n              );\n            }\n\n            // save inital quadruple using the named or blank node as object\n            // e.g.  datasetId  dct:contactPoint  blankNode/namedNode\n            RDFdataset.addQuad(\n              N3.DataFactory.quad(\n                mainURI,\n                N3.DataFactory.namedNode(\n                  generalHelper.addNamespace(key, dpiConfig)\n                ),\n                groupBlankNode\n              )\n            );\n\n            convertPropertyValues(\n              RDFdataset,\n              data[key],\n              property,\n              groupBlankNode,\n              mainType,\n              false,\n              dpiConfig,\n              dpiConfig\n            );\n          }\n        }\n      } else if (key === \"dcat:temporalResolution\") {\n        // temporal resolution is displayed as group of input forms for each property (year, month, day, ...)\n        // the form provides the data as following: [ { 'Year': '...', 'Month': '...', ... } ]\n        // the final format of this property should look like this: P?Y?M?DT?H?M?S\n        // not all values must be filled and therefore be present -> default behavior if not given: value = 0\n\n        const resolutionValues = data[key];\n        const valueString = `P${\n          resolutionValues.Year ? resolutionValues.Year : 0\n        }Y${resolutionValues.Month ? resolutionValues.Month : 0}M${\n          resolutionValues.Day ? resolutionValues.Day : 0\n        }DT${resolutionValues.Hour ? resolutionValues.Hour : 0}H${\n          resolutionValues.Minute ? resolutionValues.Minute : 0\n        }M${resolutionValues.Second ? resolutionValues.Second : 0}S`;\n\n        // frontend always provides temporalResolution even if there is no value resulting in P0Y0M0DT0H0M0S\n        // don't save if value is equal to P0Y0M0DT0H0M0S\n        if (valueString !== \"P0Y0M0DT0H0M0S\") {\n          RDFdataset.addQuad(\n            N3.DataFactory.quad(\n              mainURI,\n              N3.DataFactory.namedNode(\n                generalHelper.addNamespace(key, dpiConfig)\n              ),\n              N3.DataFactory.literal(\n                valueString,\n                N3.DataFactory.namedNode(\n                  generalHelper.addNamespace(\"xsd:duration\", dpiConfig)\n                )\n              )\n            )\n          );\n        }\n      } else if (key === \"dct:identifier\") {\n        // form provides data as array of objects with strings: [ { '@value': 'string1' }, { '@value': 'string2' }, ... ]\n        // create quadruple for each given object in the array\n        for (let valueId = 0; valueId < data[key].length; valueId += 1) {\n          const currentValue = data[key][valueId];\n          if (has(currentValue, \"@value\") && !isEmpty(currentValue[\"@value\"])) {\n            RDFdataset.addQuad(\n              N3.DataFactory.quad(\n                mainURI,\n                N3.DataFactory.namedNode(\n                  generalHelper.addNamespace(key, dpiConfig)\n                ),\n                N3.DataFactory.literal(currentValue[\"@value\"])\n              )\n            );\n          }\n        }\n      } else if (key === \"dct:rights\") {\n        // rights has a static type (RightsStatement) which needs to be added to linked data as additional node\n        // therefore we need to create an initial quadruple for with 'rights' being the predicate having a blank node\n        // blank node serves as subject for the following quadruples which contain the type and actual value of the form field\n        // RDF:\n        // datasetID  dct:rights  blankNodeID\n        //   blankNodeId rdf:type RightsStatement\n        //   blankNodeId  rdfs:label  LabelValue\n\n        // blank node as object for inital quadruple and also as subject for following quadruples\n        const rightsBlankNode = N3.DataFactory.blankNode(\"\");\n\n        RDFdataset.addQuad(\n          N3.DataFactory.quad(\n            mainURI,\n            N3.DataFactory.namedNode(\n              generalHelper.addNamespace(key, dpiConfig)\n            ),\n            rightsBlankNode\n          )\n        );\n\n        // add additional type declaration\n        RDFdataset.addQuad(\n          N3.DataFactory.quad(\n            rightsBlankNode,\n            N3.DataFactory.namedNode(\n              generalHelper.addNamespace(\"rdf:type\", dpiConfig)\n            ),\n            N3.DataFactory.namedNode(\n              generalHelper.addNamespace(\"dct:RightsStatement\", dpiConfig)\n            )\n          )\n        );\n\n        // rights is a conditional property and provides either an URI or a string ( { rdfs:label : 'URL/string' } )\n        let rightsValue;\n\n        if (data[key][\"@type\"] === \"url\") {\n          rightsValue = N3.DataFactory.namedNode(data[key][\"rdfs:label\"]);\n        } else {\n          rightsValue = N3.DataFactory.literal(data[key][\"rdfs:label\"]);\n        }\n\n        // add actual value\n        RDFdataset.addQuad(\n          N3.DataFactory.quad(\n            rightsBlankNode,\n            N3.DataFactory.namedNode(\n              generalHelper.addNamespace(\"rdfs:label\", dpiConfig)\n            ),\n            rightsValue\n          )\n        );\n      }\n    }\n  }\n}\n\n/**\n * Creates additional quads depending on given property and saves them to given RDF dataset\n * @param {N3.Writer} RDFdataset RDF dataset the quads are saved to\n * @param {Object} data Object containing data as key-value pairs\n * @param {DataFactory.namedNode} mainURI NamedNode defining URI of current property graph\n * @param {DataFactory} mainType NamedNode defining type of current property graph\n * @param {String} property String determining which property is converted (datasets/distributions/catalogues)\n * @param {String} datasetURI URI of dataset used to add distribution URI to dct:distribution within dataset graph\n */\nfunction setAdditionalProperties(\n  RDFdataset,\n  data,\n  mainURI,\n  mainType,\n  property,\n  datasetURI,\n  dpiConfig\n) {\n  // adding id and type of property\n  RDFdataset.addQuad(\n    N3.DataFactory.quad(\n      mainURI,\n      N3.DataFactory.namedNode(\n        generalHelper.addNamespace(\"rdf:type\", dpiConfig)\n      ),\n      N3.DataFactory.namedNode(mainType)\n    )\n  );\n\n  // catalogues always have to contain the property dct:type with the value 'dcat-ap'\n  if (property === \"catalogues\") {\n    RDFdataset.addQuad(\n      N3.DataFactory.quad(\n        mainURI,\n        N3.DataFactory.namedNode(\n          generalHelper.addNamespace(\"dct:type\", dpiConfig)\n        ),\n        N3.DataFactory.literal(\"dcat-ap\")\n      )\n    );\n  }\n\n  // add distribution id to dataset graph (dcat:distribution)\n  if (property === \"distributions\") {\n    RDFdataset.addQuad(\n      N3.DataFactory.quad(\n        N3.DataFactory.namedNode(datasetURI),\n        N3.DataFactory.namedNode(\n          generalHelper.addNamespace(\"dcat:distribution\", dpiConfig)\n        ),\n        mainURI\n      )\n    );\n  }\n}\n\n//-----------------------------------------------------------------------------------------------------\n//            basic conversion (input to RDF) methods for different categories of data\n//-----------------------------------------------------------------------------------------------------\n// seems unnecessary at first but if we want to convert nested properties as well, we need these\n// methods (especially to provide the correct parent URI)\n\n/**\n * Converts provided data to quad and saves it to given dataset\n * @param {N3.Writer} RDFdataset Dataset the converter saves the converted data to\n * @param {DataFactory} id Node (Blank or Named) used as subject in quad\n * @param {String} data Data given by form used as object in quad\n * @param {String} key Name of current value (e.g. dct:title) used as predicate in quad\n */\nfunction convertSingularString(RDFdataset, id, data, key, dpiConfig) {\n  if (!isEmpty(data[key])) {\n    RDFdataset.addQuad(\n      N3.DataFactory.quad(\n        id,\n        N3.DataFactory.namedNode(generalHelper.addNamespace(key, dpiConfig)),\n        N3.DataFactory.literal(data[key])\n      )\n    );\n  }\n}\n\n/**\n * Converts provided data to quad and saves it to given dataset\n * @param {N3.Writer} RDFdata Dataset the converter saves the converted data to\n * @param {DataFactory} id Node (Blank or Named) used as subject in quad\n * @param {String} data Data given by form used as object in quad\n * @param {String} key Name of current value (e.g. dct:title) used as predicate in quad\n */\nfunction convertSingularURI(RDFdataset, id, data, key, dpiConfig) {\n  // there are two different formats the frontend delivers URIs\n  // 1: 'URI' or 2: {'name': 'abc', 'resource': 'URI'}\n\n  // URIs can either be a normal URL or an email address\n  // mail addresses typicall include '@' which is used to determine if the given string is a normal URL or an email address\n \n  if (!isEmpty(data[key])) {\n    let singleURI;\n\n    if (typeof data[key] === \"object\") {\n      if (has(data[key], \"resource\")) {\n        singleURI = data[key].resource;\n      }\n    } else {\n      if (data[key].includes(\"@\")) {\n        // mail address\n        singleURI = `mailto:${data[key]}`;\n      } else {\n        // normal URL\n        \n        singleURI = data[key];\n      }\n    }\n\n    // save quad to dataset\n    RDFdataset.addQuad(\n      N3.DataFactory.quad(\n        id,\n        N3.DataFactory.namedNode(generalHelper.addNamespace(key, dpiConfig)),\n        N3.DataFactory.namedNode(singleURI)\n      )\n    );\n  }\n}\n\n/**\n * Converts provided data to quads and saves them to given dataset\n * @param {N3.Writer} RDFdataset Dataset the converter saves the converted data to\n * @param {DataFactory} id Node (Blank or Named) used as subject in quads\n * @param {Array} data Array containing URLs used as object within quads\n * @param {String} key Name of current value (e.g. dct:title) used as predicate in quads\n * @param {String} property Determining which property is concerted (datasets/distributions/catalogues)\n */\nfunction convertMultipleURI(RDFdataset, id, data, key, property, dpiConfig) {\n  // there are two different formats the frontend delivers multiple URIs\n  // 1: [ {\"name\": '...', \"resource\": 'URI'}, {...} ] -> multi-autocomplete fields\n  // 2: [ { \"@id\": \"URI1\" }, { \"@id\": \"URI2\" } ] repeatable fields\n\n  for (let uriIndex = 0; uriIndex < data[key].length; uriIndex += 1) {\n    let currentURI;\n    const valueObject = data[key][uriIndex];\n    if (!isEmpty(valueObject)) {\n      if (has(valueObject, \"resource\")) currentURI = valueObject.resource;\n      else if (has(valueObject, \"@id\")) currentURI = valueObject[\"@id\"];\n    }\n\n    // save quad to dataset\n    RDFdataset.addQuad(\n      N3.DataFactory.quad(\n        id,\n        N3.DataFactory.namedNode(generalHelper.addNamespace(key, dpiConfig)),\n        N3.DataFactory.namedNode(currentURI)\n      )\n    );\n  }\n}\n\n/**\n * Converts provided data to quad and saves them to given dataset\n * @param {N3.Writer} RDFdataset Dataset the converter saves the converted data to\n * @param {DataFactory} id Node (Blank or Named) used as subject in quad\n * @param {String} data String data used as object with type in quad\n * @param {String} key Name of current value (e.g. dct:title) used as predicate in quad and to determine quad-object type\n */\nfunction convertTypedString(RDFdataset, id, data, key, dpiConfig) {\n  if (!isEmpty(data[key])) {\n    // there is a variety of properties which can have different types\n    // issued and motified already provide a type definition ({'@type': 'date/datetime', '@value': '...'})\n    if (key === \"dct:issued\" || key === \"dct:modified\") {\n      if (has(data[key], \"@value\") && !isEmpty(data[key][\"@value\"])) {\n        const imValueType =\n          data[key][\"@type\"] === \"date\" ? data[key][\"@type\"] : \"dateTime\";\n        const valueType = generalHelper.addNamespace(\n          `xsd:${imValueType}`,\n          dpiConfig\n        );\n\n        /// save quad to dataset\n        RDFdataset.addQuad(\n          N3.DataFactory.quad(\n            id,\n            N3.DataFactory.namedNode(\n              generalHelper.addNamespace(key, dpiConfig)\n            ),\n            N3.DataFactory.literal(\n              data[key][\"@value\"],\n              N3.DataFactory.namedNode(valueType)\n            )\n          )\n        );\n      }\n    } else {\n      // all other properties are given as a simple string\n      let valueType;\n      if (key === \"dcat:endDate\" || key === \"dcat:startDate\") {\n        // dcat:endDate and dcat:startDate are xsd:dateTime\n        valueType = generalHelper.addNamespace(\"xsd:dateTime\", dpiConfig);\n      } else if (\n        key === \"dcat:spatialResolutionInMeters\" ||\n        key === \"dcat:byteSize\"\n      ) {\n        // dcat:spatialResolutionInMeters and dcat:byteSize are xsd:decimal\n        valueType = generalHelper.addNamespace(\"xsd:decimal\", dpiConfig);\n      } else if (key === \"pv:distributionType\") {\n        valueType = generalHelper.addNamespace(\"xsd:string\", dpiConfig);\n        if (\n          data[key][\"@Tag\"] === \"LeadingWidget\" ||\n          data[key][\"lead\"] === \"true\"\n        ) {\n          data[key] = \"Widget\";\n          RDFdataset.addQuad(\n            N3.DataFactory.quad(\n              id,\n              N3.DataFactory.namedNode(\n                generalHelper.addNamespace(\"pv:isLeading\", dpiConfig)\n              ),\n              N3.DataFactory.literal(true)\n            )\n          );\n        }\n        if (data[key][\"@Tag\"] === \"Widget\") {\n          data[key] = \"Widget\";\n        } else data[key] = data[key];\n      }\n\n      /// save quad to dataset\n      RDFdataset.addQuad(\n        N3.DataFactory.quad(\n          id,\n          N3.DataFactory.namedNode(generalHelper.addNamespace(key, dpiConfig)),\n          N3.DataFactory.literal(data[key], N3.DataFactory.namedNode(valueType))\n        )\n      );\n    }\n  }\n}\n\n/**\n * Converts provided data to quads and saves them to given dataset\n * @param {N3.Writer} RDFdataset Dataset the converter saves the converted data to\n * @param {DataFactory} id Node (Blank or Named) used as subject in quads\n * @param {Array} data Array of objects containing data and language converted into literal with language for quad\n * @param {String} key Name of current value (e.g. dct:title) used as predicate in quads\n */\nfunction convertMultilingual(RDFdataset, id, data, key, dpiConfig) {\n  // multilingual fields mostly provide data as followed\n  // [ { '@value': '....', '@language': '...' }, ... ]\n  // only the licence title provides no language\n\n  if (!isEmpty(data[key])) {\n    // licence title\n    if (!Array.isArray(data[key])) {\n      RDFdataset.addQuad(\n        N3.DataFactory.quad(\n          id,\n          N3.DataFactory.namedNode(generalHelper.addNamespace(key, dpiConfig)),\n          N3.DataFactory.literal(data[key])\n        )\n      );\n    } else {\n      for (let langIndex = 0; langIndex < data[key].length; langIndex += 1) {\n        const currentData = data[key][langIndex];\n        // only save data if a value is given (forntend provides preselected language which don't need to be saved if there is no actaul value)\n        if (\n          !isEmpty(currentData) &&\n          has(currentData, \"@value\") &&\n          !isEmpty(currentData[\"@value\"])\n        ) {\n          let languageTag;\n\n          // if there is no langauge given, set language to english\n          if (\n            !has(currentData, \"@language\") ||\n            isEmpty(currentData, \"@language\")\n          ) {\n            languageTag = \"en\";\n          } else {\n            // if language is given, use given tag\n            languageTag = currentData[\"@language\"];\n          }\n\n          // saving quad to dataset\n          RDFdataset.addQuad(\n            N3.DataFactory.quad(\n              id,\n              N3.DataFactory.namedNode(\n                generalHelper.addNamespace(key, dpiConfig)\n              ),\n              N3.DataFactory.literal(currentData[\"@value\"], languageTag)\n            )\n          );\n        }\n      }\n    }\n  }\n}\n\nexport default {\n  convertToRDF,\n};\n"],"names":["convertToRDF","data","property","specification","finishedRDFdata","dpiConfig","RDFdata","N3","datasetURI","convertPropertyValues","index","error","result","RDFdataset","preMainURI","preMainType","setMain","formatTypes","mainURI","mainType","generalHelper","randomId","setAdditionalProperties","valueKeys","key","convertSingularString","convertSingularURI","convertMultipleURI","convertTypedString","convertMultilingual","actualData","groupId","currentGroupData","isEmpty","has","notationValue","groupBlankNode","emptyPage","hasTitle","hasDescription","hasNoValueKeysTitle","hasEmptyValueTitle","hasNoValueKeysDescription","hasEmptyValueDescription","el","resolutionValues","valueString","valueId","currentValue","rightsBlankNode","rightsValue","id","singleURI","uriIndex","currentURI","valueObject","imValueType","valueType","langIndex","currentData","languageTag","toRDF"],"mappings":"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"}