Art Gallery RDF Application - Technical Documentation

Version: 1.0.0

Last Updated: 2025-02-03

Authors: Feraru Ionut, Nastase Valentin-Codrin

Table of Contents

1. Introduction

This document provides comprehensive technical documentation for the Art Gallery RDF Application, a semantic web application designed to manage and query art-related data using RDF and SPARQL technologies.

1.1 Purpose

The application serves as a platform for exploring and analyzing art collections, providing detailed information about paintings, sculptures, and museums through semantic web technologies.

1.2 Technology Stack

2. System Architecture

Architecture diagram

2.1 Component Overview

Component Description Technologies
UI Microservice Handles user interface and client-side logic .NET Razor, JavaScript
RDF Service Manages RDF data and SPARQL queries .NET Core, RDF.NET

3. Microservices

3.1 UI Microservice

Project Structure:
/Pages
    /Models
    /Museums
    /Sculptures
    /DataAnalyzer
/wwwroot
    /js
    /css
    /lib
    

3.2 RDF Service

Main Endpoints:

GET /rdf/{property}
POST /rdf/validate

4. RDF Ontology

The application utilizes a custom ontology for representing art-related concepts and relationships.

4.1 Core Ontology Classes

art:Artist
    a owl:Class ;
    rdfs:label "Artist"@en ;
    rdfs:subClassOf foaf:Person .

art:Painter
    a owl:Class ;
    rdfs:label "Painter"@en ;
    rdfs:subClassOf art:Artist .

art:Influence
    a owl:Class ;
    rdfs:label "Influence"@en .

art:TimePeriod
    a owl:Class ;
    rdfs:label "Time Period"@en .
    

4.2 Property Definitions

art:hasName
    a owl:DatatypeProperty ;
    rdfs:domain art:Artist ;
    rdfs:range xsd:string .

art:birthDate
    a owl:DatatypeProperty ;
    rdfs:domain art:Artist ;
    rdfs:range xsd:date .

art:influencedBy
    a owl:ObjectProperty ;
    rdfs:domain art:Artist ;
    rdfs:range art:Influence .

art:hasType
    a owl:ObjectProperty ;
    rdfs:range owl:Class .
    

4.3 SHACL Validation Framework

SHACL shapes are used to validate the RDF data against the ontology schema.

Node shape definitions

# Artist Shape Definition
art:ArtistShape
    a sh:NodeShape ;
    sh:targetClass art:Artist ;
    sh:property [
        sh:path art:hasName ;
        sh:datatype xsd:string ;
        sh:minCount 1 ;
    ] ;
    sh:property [
        sh:path art:birthDate ;
        sh:datatype xsd:date ;
        sh:pattern "^[0-9]{4}-[0-9]{2}-[0-9]{2}$" ;
    ] .

# Painter Shape Definition
art:PainterShape
    a sh:NodeShape ;
    sh:targetClass art:Painter ;
    sh:property [
        sh:path art:technique ;
        sh:class art:PaintingTechnique ;
    ] .
    

Property Shapes and Constraints

# Name Property Constraints
art:hasNameShape
    a sh:PropertyShape ;
    sh:path art:hasName ;
    sh:minCount 1 ;
    sh:maxCount 1 ;
    sh:nodeKind sh:Literal ;
    sh:pattern "^[A-Za-z\\s-]+$" .

# Birth Date Constraints
art:birthDateShape
    a sh:PropertyShape ;
    sh:path art:birthDate ;
    sh:datatype xsd:date ;
    sh:minInclusive "1850-01-01"^^xsd:date ;
    sh:maxInclusive "1900-12-31"^^xsd:date .
    

4.4 RDF Data Model

The RDF data model represents artists, paintings, and influences in a graph structure.

Artist Instance Example

art:HenriMatisse
a art:Artist ;
art:hasName "Henri Matisse" ;
art:birthDate "1869-12-31"^^xsd:date ;
art:influencedBy art:VeniceBiennale ;
art:wikidata "Q5589" ;
art:exhibited art:ArmoryShow .
    

Exhibition Instance Example

art:VeniceBiennale
a art:Influence ;
art:hasName "Venice Biennale" ;
art:hasType art:Exhibition ;
art:wikidata "Q205751" ;
art:startDate "1895"^^xsd:gYear .
    

4.5 Semantic Relationships

Relationship Types

1. **Hierarchical Relations**
   - extends (Class inheritance)
   - instance_of (Individual-Class relationship)

2. **Property Relations**
   - has_property (Shape-Property connection)
   - has_constraint (Property-Constraint binding)

3. **Domain-Specific Relations**
   - exhibited_at (Artist-Exhibition connection)
   - influenced_by (Artist influence mapping)
    

Validation Rules

# Example SPARQL query for validation
SELECT ?artist ?exhibition
WHERE {
    ?artist a art:Artist ;
            art:exhibited ?exhibition .
    ?exhibition a art:Influence .
    FILTER NOT EXISTS {
        ?exhibition art:startDate ?date .
        FILTER (?date < ?artist art:birthDate)
    }
}
    

4.6 SHACL Validation Implementation

Core Validation Rules

# Artist Validation Rules
art:ArtistValidation
    a sh:NodeShape ;
    sh:targetClass art:Artist ;
    sh:property [
        sh:path art:wikidata ;
        sh:pattern "^Q[0-9]+$" ;
        sh:minCount 1 ;
        sh:maxCount 1 ;
    ] ;
    sh:property [
        sh:path art:exhibited ;
        sh:class art:Influence ;
        sh:minCount 0 ;
    ] .
    

Complex Validation Patterns

# Exhibition Date Validation
art:ExhibitionDateValidation
    a sh:NodeShape ;
    sh:targetClass art:Influence ;
    sh:property [
        sh:path art:startDate ;
        sh:datatype xsd:gYear ;
        sh:minInclusive "1850"^^xsd:gYear ;
        sh:maxInclusive "1950"^^xsd:gYear ;
    ] .
    

4.7 Ontology Statistics

4.8 Adhering to the linked data principles

1. Use URIs as Names for Things

Implementation

Our ontology consistently uses URIs to identify:

Example
@prefix wd: <http://www.wikidata.org/entity/> .
@prefix art: <http://example.org/art/ontology#> .

wd:Q762 a art:Artist ;  # Vincent van Gogh
art:hasInfluence wd:Q34661 .  # Impressionism
    
Compliance Assessment

2. Use HTTP URIs

Implementation

Our ontology uses HTTP URIs for:

URI Structure
Base URI: http://example.org/art/ontology#
Wikidata Entities: http://www.wikidata.org/entity/
Properties: http://www.wikidata.org/prop/direct/
    
Compliance Assessment

3. Provide Useful Information Using RDF Standards

Implementation

Information is provided using:

Data Model Example
# Artist Definition
art:Artist rdf:type owl:Class ;
    rdfs:label "Artist"@en ;
    rdfs:comment "A person who creates art"@en .

# Influence Relationship
art:hasInfluence rdf:type owl:ObjectProperty ;
rdfs:domain art:Artist ;
rdfs:range art:Influence .
    
Properties and Relationships
  1. Core Properties:
    • art:hasInfluence
    • art:birthDate
    • art:deathDate
    • art:influenceType
  2. Data Properties:
    • Labels in multiple languages
    • Temporal information
    • Source references
Compliance Assessment
Validation

5. Features and Pages

The project is using Wikidata over DBPedia because of the following reasons:

  1. Has more comprehensive data about artistic influences
  2. Includes both direct influences and inspirations
  3. Provides better structured information about the type of influence
  4. Has more consistent data quality
  5. Is generally more up-to-date

5.1 Paintings Page

Implements SPARQL queries for painting-related data:

  1. Get works of art for Vincent van Gogh:
    SELECT DISTINCT ?work ?workLabel ?workImage ?artist ?artistLabel ?museum ?museumLabel WHERE {  
      ?work wdt:P170 wd:Q5582.  OPTIONAL { ?work wdt:P18 ?workImage. }  
      OPTIONAL { ?work wdt:P170 ?artist. }  OPTIONAL { ?work wdt:P276 ?museum. }  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }}  
    LIMIT 20
  2. Get works of art for Leonardo da Vinci:
    SELECT DISTINCT ?work ?workLabel ?workImage ?artist ?artistLabel ?museum ?museumLabel WHERE {  
        ?work wdt:P170 wd:Q762.  # Created by Claude Monet (Q762)    OPTIONAL { ?work wdt:P18 ?workImage. }  # Optional: image of the painting    OPTIONAL { ?work wdt:P170 ?artist. }    # Optional: artist of the painting    OPTIONAL { ?work wdt:P276 ?museum. }    # Optional: museum where the painting is locatedSERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }  
    }  
    LIMIT 20
  3. Get similar artists to Vincent van Gogh:
    SELECT DISTINCT ?property ?propertyLabel ?artist1Value ?artist1ValueLabel ?artist2Value ?artist2ValueLabel WHERE {  
        # Proprietăți și valori pentru artistul 1    OPTIONAL {        wd:${artist1Id} ?property ?artist1Value.        FILTER(?artist1Value != "" && ?artist1Value != "N/A").    }    # Proprietăți și valori pentru artistul 2    OPTIONAL {        wd:${artist2Id} ?property ?artist2Value.        FILTER(?artist2Value != "" && ?artist2Value != "N/A").    }    # Adăugare etichete pentru proprietăți și valori    SERVICE wikibase:label {        bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en".  
            ?property rdfs:label ?propertyLabel.        ?artist1Value rdfs:label ?artist1ValueLabel.        ?artist2Value rdfs:label ?artist2ValueLabel.    }    # Filtru pe proprietăți relevante    FILTER(?property IN (wdt:P135, wdt:P106, wdt:P569, wdt:P570, wdt:P27, wdt:P19, wdt:P20, wdt:P18, wdt:P800, wdt:P937)) # Mișcare, profesie, naștere, deces}
  4. Get similar artists to Leonardo da Vinci:
    SELECT DISTINCT ?property ?propertyLabel ?artist1Value ?artist1ValueLabel ?artist2Value ?artist2ValueLabel WHERE {  
        # Proprietăți și valori pentru artistul 1    OPTIONAL {        wd:${artist1Id} ?property ?artist1Value.        FILTER(?artist1Value != "" && ?artist1Value != "N/A").    }    # Proprietăți și valori pentru artistul 2    OPTIONAL {        wd:${artist2Id} ?property ?artist2Value.        FILTER(?artist2Value != "" && ?artist2Value != "N/A").    }    # Adăugare etichete pentru proprietăți și valori    SERVICE wikibase:label {        bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en".  
            ?property rdfs:label ?propertyLabel.        ?artist1Value rdfs:label ?artist1ValueLabel.        ?artist2Value rdfs:label ?artist2ValueLabel.    }    # Filtru pe proprietăți relevante    FILTER(?property IN (wdt:P135, wdt:P106, wdt:P569, wdt:P570, wdt:P27, wdt:P19, wdt:P20, wdt:P18, wdt:P800, wdt:P937)) # Mișcare, profesie, naștere, deces}
  5. Get artists influenced by Vincent van Gogh:
    PREFIX icon:   
    PREFIX wdt:   
    PREFIX wd:   
    PREFIX rdfs:   
    PREFIX owl:   
    SELECT DISTINCT ?artist ?artistLabel ?work ?workLabel ?workImage WHERE {  
        ?artist wdt:P737 wd:Q5582.  # Influenced by Van Gogh (Q5582)    ?artist wdt:P106 wd:Q1028181.  # Occupation: painter    OPTIONAL {        ?work wdt:P170 ?artist.        ?work rdfs:label ?workLabel.        OPTIONAL { ?work wdt:P18 ?workImage. }    }    OPTIONAL {        ?artist icon:hasInfluence ?influence.        ?influence rdfs:label ?influenceLabel.    }    SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }}
  6. Get artists influences between 1850 and 1900:
    #title: Painting born 1850-1900 and their influences  
    #defaultView:Table  
    SELECT DISTINCT ?artist ?artistLabel ?birthDate ?influence ?influenceLabel ?influenceTypeLabel WHERE {  
      ?artist wdt:P106 wd:Q1028181;  # occupation: artist         wdt:P569 ?birthDate;    # date of birth         wdt:P737|wdt:P941 ?influence.  # influenced by (P737) OR inspired by (P941)  
      # Get the type of the influence (person, movement, event, etc)  ?influence wdt:P31 ?influenceType.  
      # Filter for artists born between 1850 and 1900  FILTER(YEAR(?birthDate) >= 1850 && YEAR(?birthDate) <= 1900)  
      # Get labels in the selected language  SERVICE wikibase:label {    bd:serviceParam wikibase:language "${selectedLanguage},en".  
        ?artist rdfs:label ?artistLabel.    ?influence rdfs:label ?influenceLabel.    ?influenceType rdfs:label ?influenceTypeLabel.  }}  
    ORDER BY ?artistLabel ?birthDate  
    LIMIT 1000
  7. Get paintings influenced by Van Gogh:
    PREFIX icon:   
    PREFIX wdt:   
    PREFIX wd:   
    PREFIX rdfs:   
    PREFIX owl:   
      
    SELECT ?artist ?artistLabel WHERE {  
        ?artist wdt:P737 wd:Q5582.  # Influenced by Vincent van Gogh (Q5582)    ?artist wdt:P106 wd:Q1028181.  # Occupation: painter    ?artist wdt:P31 wd:Q5.         # Instance of: human    OPTIONAL { ?artist icon:hasInfluence ?influenceDescription. }    SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }}
    SELECT ?work ?workLabel ?workImage WHERE {  
        ?work wdt:P170 wd:${painterId}.  # Created by the painter  
        ?work wdt:P31 wd:Q3305213.  # Instance of painting (Q3305213)    OPTIONAL { ?work wdt:P18 ?workImage. }    SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }}  
    LIMIT 3

5.2 Museums Page

Implements SPARQL queries for comparing artists and museums in a creative way

  1. Compare Paintings:
    PREFIX wd:   
    PREFIX wdt:   
    PREFIX schema:   
    SELECT ?painting ?title ?museumName ?image WHERE {  
        ?painting wdt:P170 wd:${artist} .    ?painting wdt:P276 ?museum .    ${filterCondition} .    ?museum rdfs:label ?museumName .    ?painting rdfs:label ?title .    OPTIONAL { ?painting wdt:P18 ?image. }    FILTER (lang(?title) = "en" && lang(?museumName) = "en")}
  2. Find Museums and Other Artists
    For artists:
    
    PREFIX wd:   
    PREFIX wdt:   
      
    SELECT DISTINCT ?museumLabel (SAMPLE(?otherArtist) AS ?otherArtist) (SAMPLE(?otherArtistLabel) AS ?otherArtistLabel) WHERE {  
        VALUES ?museum { ${museumIds} }    ?otherPainting wdt:P170 ?otherArtist;                   wdt:P276 ?museum.  
        FILTER (?otherArtist != wd:${artist})  
      
        SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }}  
    GROUP BY ?museumLabel  
    ORDER BY ?museumLabel
    
    For paintings:
    PREFIX wd:   
    PREFIX wdt:   
      
    SELECT DISTINCT ?museumLabel ?otherArtistLabel (SAMPLE(?otherPaintingLabel) AS ?otherPaintingLabel) (SAMPLE(?paintingImage) AS ?paintingImage) WHERE {  
        VALUES ?museum { ${museumIds} }    VALUES ?otherArtist { ${artistIds} }        ?otherPainting wdt:P170 ?otherArtist;  
                       wdt:P276 ?museum.  
        OPTIONAL { ?otherPainting rdfs:label ?otherPaintingLabel. FILTER(LANG(?otherPaintingLabel) = "en") }    OPTIONAL { ?otherPainting wdt:P18 ?paintingImage }  
        SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }}  
    GROUP BY ?museumLabel ?otherArtistLabel  
    ORDER BY ?museumLabel
  3. Find Similar Paintings:
    PREFIX wd:   
    PREFIX wdt:   
      
    SELECT DISTINCT ?museumLabel ?otherArtistLabel ?otherPaintingLabel ?paintingImage WHERE {  
        VALUES ?museum { ${museumIds} }    VALUES ?otherArtist { ${artistIds} }        ?otherPainting wdt:P170 ?otherArtist;  
                       wdt:P276 ?museum.  
        OPTIONAL { ?otherPainting rdfs:label ?otherPaintingLabel. FILTER(LANG(?otherPaintingLabel) = "en") }    OPTIONAL { ?otherPainting wdt:P18 ?paintingImage }  
        FILTER EXISTS { ?otherPainting wdt:P18 ?paintingImage }  # ✅ Ensure we only get paintings with images  
        SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }}  
    ORDER BY ?museumLabel  
    LIMIT 5

5.3 Sculptures Page

Provides detailed information about sculptural works and their locations.

  1. List of Famous Sculptures:
    SELECT ?sculpture ?sculptureLabel ?artist ?artistLabel ?creationDate ?location ?locationLabel ?image WHERE {  
        ?sculpture wdt:P31 wd:Q860861 .  # Instance of sculpture    ?sculpture wdt:P170 ?artist .     # Creator    OPTIONAL { ?sculpture wdt:P571 ?creationDate . }  # Creation date    OPTIONAL { ?sculpture wdt:P276 ?location . }      # Location    OPTIONAL { ?sculpture wdt:P18 ?image . }          # Image    SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }}  
    LIMIT 50
  2. Sculptures by a Specific Artist:
    SELECT ?sculpture ?sculptureLabel ?creationDate ?image WHERE {  
        ?sculpture wdt:P31 wd:Q860861 .  # Instance of sculpture    ?sculpture wdt:P170 wd:${artist} .    OPTIONAL { ?sculpture wdt:P571 ?creationDate . }  # Creation date    OPTIONAL { ?sculpture wdt:P18 ?image . }          # Image    SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }}  
    LIMIT 50
  3. Sculptures in a Specific Museum:
    SELECT ?sculpture ?sculptureLabel ?artist ?artistLabel ?image WHERE {  
        ?sculpture wdt:P31 wd:Q860861 .  # Instance of sculpture    ?sculpture wdt:P276 wd:${museum} .    OPTIONAL { ?sculpture wdt:P170 ?artist . }  # Creator  
        OPTIONAL { ?sculpture wdt:P18 ?image . }    # Image    SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }}  
    LIMIT 50
  4. Sculptures by a Specific Material:
    SELECT ?sculpture ?sculptureLabel ?artist ?artistLabel ?material ?materialLabel ?image WHERE {  
        ?sculpture wdt:P31 wd:Q860861 .  # Instance of sculpture    ?sculpture wdt:P186 wd:${material} .    OPTIONAL { ?sculpture wdt:P170 ?artist . }  # Creator    OPTIONAL { ?sculpture wdt:P18 ?image . }    # Image    SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }}  
    LIMIT 50
  5. Sculptures from a Specific Period:
    SELECT DISTINCT ?sculpture ?sculptureLabel ?artist ?artistLabel ?inception ?image WHERE {  
      ?sculpture wdt:P31 wd:Q860861.  # Instance of sculpture  ?sculpture wdt:P170 ?artist.    # Has artist  ?sculpture wdt:P571 ?inception. # Inception date  ?sculpture wdt:P18 ?image.      # Must have an image  
      # Ensure sculpture and artist have English labels  ?sculpture rdfs:label ?sculptureLabel.FILTER(LANG(?sculptureLabel) = "en")    
      ?artist rdfs:label ?artistLabel.  # Ensure artist has a name  FILTER(LANG(?artistLabel) = "en")   
      FILTER (?inception >= "${startDate}T00:00:00Z"^^xsd:dateTime &&  
              ?inception <= "${endDate}T23:59:59Z"^^xsd:dateTime)  
      
      SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }}  
    ORDER BY ?inception  
    LIMIT 50

5.4 Ontology Visualization

Interactive visualization of the RDF schema using [Your Visualization Library].

SHACL Validation and Artist Influences Ontology Visualization

A detailed analysis of a D3.js-based visualization system representing SHACL shapes and artist influences in an ontological structure, with particular focus on RDF data modeling, SHACL validation patterns, and semantic relationships.

6. Deployment

The application is publicly available on

7. Detailed Technology Stack Analysis

7.1 Frontend Technologies

HTML5 & CSS3

JavaScript Implementation

// Example of SPARQL Query Handler
export async function getFamousSculptures() {
    const query = `
        SELECT ?sculpture ?sculptureLabel ?artist ?artistLabel ?creationDate ?location ?locationLabel ?image WHERE {
            ?sculpture wdt:P31 wd:Q860861 .  # Instance of sculpture
            ?sculpture wdt:P170 ?artist .     # Creator
            OPTIONAL { ?sculpture wdt:P571 ?creationDate . }  # Creation date
            OPTIONAL { ?sculpture wdt:P276 ?location . }      # Location
            OPTIONAL { ?sculpture wdt:P18 ?image . }          # Image
            SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
        }
        LIMIT 50
    `;
    const url = "https://query.wikidata.org/sparql?query=" + encodeURIComponent(query);
    const response = await fetch(url, {
        headers: {
            'Accept': 'application/sparql-results+json'
        }
    });
    const data = await response.json();
    await displaySculptureResults(data);
    
}

// Example of RDF Data Visualization
const resultsContainer = document.getElementById('results');
    resultsContainer.innerHTML = ''; // Clear previous results

    const table = document.createElement('table');
    table.style.width = '100%';
    table.style.borderCollapse = 'collapse';

    // Add headers for the table
    const headerRow = document.createElement('tr');
    const headers = ['Image', 'Title', 'Creation Date'];
    headers.forEach(headerText => {
        const header = document.createElement('th');
        header.textContent = headerText;
        header.style.border = '1px solid #ddd';
        header.style.padding = '8px';
        header.style.textAlign = 'left';
        header.style.backgroundColor = '#f2f2f2';
        headerRow.appendChild(header);
    });
    table.appendChild(headerRow);

    const titlesSet = new Set();

    if (data.results.bindings.length === 0) {
        const noResultsRow = document.createElement('tr');
        const noResultsCell = document.createElement('td');
        noResultsCell.colSpan = headers.length;
        noResultsCell.textContent = 'No results found.';
        noResultsCell.style.textAlign = 'center';
        noResultsCell.style.padding = '8px';
        noResultsRow.appendChild(noResultsCell);
        table.appendChild(noResultsRow);
    } else {
        data.results.bindings.forEach(item => {
            if (item.image) {
                const title = item.sculptureLabel.value;
                if (!titlesSet.has(title)) {
                    titlesSet.add(title);

                    const row = document.createElement('tr');

                    // Image column
                    const imgCell = document.createElement('td');
                    imgCell.style.border = '1px solid #ddd';
                    imgCell.style.padding = '8px';
                    const img = document.createElement('img');
                    img.src = item.image.value;
                    img.alt = title;
                    img.width = 100;
                    img.height = 100;
                    img.loading = 'lazy';
                    img.style.cursor = 'pointer';
                    img.addEventListener('click', () => {
                        openModal(img.src, img.alt);
                    });
                    imgCell.appendChild(img);
                    row.appendChild(imgCell);

                    // Title column
                    const titleCell = document.createElement('td');
                    titleCell.style.border = '1px solid #ddd';
                    titleCell.style.padding = '8px';
                    const link = document.createElement('a');
                    const sculptureId = item.sculpture.value.split('/').pop();
                    link.href = `https://www.wikidata.org/wiki/${sculptureId}`;
                    link.target = '_blank';
                    link.rel = 'noopener noreferrer';
                    link.textContent = title;
                    titleCell.appendChild(link);
                    row.appendChild(titleCell);

                    // Creation Date column
                    const creationDateCell = document.createElement('td');
                    creationDateCell.style.border = '1px solid #ddd';
                    creationDateCell.style.padding = '8px';
                    creationDateCell.textContent = item.creationDate ? item.creationDate.value : 'N/A';
                    row.appendChild(creationDateCell);

                    table.appendChild(row);
                }
            }
        });
    }

    resultsContainer.appendChild(table);
}
        

7.2 Backend Technologies (.NET Razor)

Core Components

7.3 RDF Service Architecture

Service Interface

8. User Interface Documentation

8.1 Models

The user can query and see different types of paintings.

Paintings Search Interface

8.2 Museums

The user can query and see different types of paintings.

Museums Search Interface And Comparison

8.3 Sculptures

Sculptures Search Interface

8.4 Data Relationships Visualizations

Data Relationships Visualizations