\chapter{Design}\label{chap:design}

This chapter is dedicated to the design of the new backend application. The current backend of the application will be replaced entirely with the new backend, as the former functionality is no longer needed after implementation. A different approach to data and its modification is used, with unified logic for the frontend part of the application.

\section{Replacement of REST API to GraphQL}

GraphQL uses a different approach to data as a REST API. When we fetch the data using the RESP API as a response, we will get the requested object with all its attributes except those representing another object. In this case, we must use join notation or send two requests (if we have two objects) to the server. This approach takes more computer resources and is more complex for a developer to implement. Also, we constantly receive the whole object and fields that we don't even need. This approach makes the responses through the network heavier.
On the other hand, GRAPHQL uses a different approach and allows us to get in the response data that we need without returning the whole object. Also, it supports getting the referenced objects as attributes without the need to do an explicit join or send two requests to the server. In this case, it is always treated as one request, and we get just one response. In the example, you can see how we can retrieve the user and their team using GRAPHQL and also the REST API.

\begin{lstlisting}[caption={REST API call and join}, label={lst:restapicalljoin},  captionpos={b}]
GET /data/user/MnOaN&?_join=memberOf -- depth one
-- memberOf = TeamInstance
GET /data/team/X&aEnO -- depth two
--from TeamInstance we get Team identifier
--and then we can get the name of the Team
\end{lstlisting}

\begin{lstlisting}[caption={GraphQL abstract with depth data filtering}, label={lst:ultragraphqlabstractdepth},  captionpos={b}]
query getInfoUserTeam{
  courses_User{
    courses_memberOf{ --type TeamInstace
      courses_approved --depth one
      courses_Team{
        courses_name --name of the team - depth two
      }
    }
  }
}
\end{lstlisting}

The additional advantage is that we can hide fields in the schema. If the field is not provided in the schema, it cannot be shown by GraphQL. With this, we can hide private data, like passwords, and not include them in the schema. To exclude them from the schema, we mark these fields as hidden, and there will not be included.

\section{Courses system schema}

The schema of the Course system represents an ontology for this system. The schema was never fully described in RDF data, but in the backend part of the application, it is written in JS form (JS object). We need a complete RDF schema for UltraGraphQL to work with our DB. Otherwise, we are only able to query some of the required fields. Therefore,  we create a script that must transfer the JS form into the RDF schema.

\section{Script for creating a schema}

The script must provide the complete RDF schema for our Course system ontology. In addition, each JS object must be mapped to RDF triples. For each JS object, there might be multiple triples provided. Therefore, a mapping must be made. Each model represents an instance of rdfs:Class which is saved in attribute type. The inheritance is allowed to be used; therefore, there exists an additional attribute subclassOf. This attribute references the parent model. Multiple subclasses are possible. Thus we can make multiple triples reference to the specific classes.

\section{UPDATE of the existing fields}

UltraGraphQL, by default, provides INSERT and DELETE actions. INSERT action is used to insert a new triple about existing or new IRI. In case we insert some attribute for the existing IRI, a new triple is made, and in the end, there are multiple queries with the same subject. In the sense of data type, this is just adding a new element to an existing one. Therefore, its type is a collection (also called a list). When we call INSERT action, it will always add a new attribute without changing the existing one.
The same also applies to the DELETE action. If we delete the identifier, it will delete all of its related triples. However, we can also delete just one specific triple, and if we have more triples with the same subject and predicate, it will just pop the specific one from the list. However, we would like to perform an action that will update the existing triple by replacing the value. Update action in SPARQL can be achieved by executing INSERT and DELETE queries. So there is no possibility of editing the existing one. However, if we INSERT and DELETE the query separately as two mutations, it would be run as two queries and two different transactions. We want to prevent that, and therefore an UPDATE action was created. Its purpose is to update the existing triple, with the logic of SPARQL, that the INSERT and DELETE script is called within one transaction. For that purpose, an additional action called UPDATE is added to the UltraGraphQL. Same as for the INSERT and DELETE actions, this action will also need access to the schema created for this action. After that, a specific query must be made that will perform delete and insert as one transaction - for the SPARQL, this is achieved by:

\begin{lstlisting}[caption={UPDATE performed through SPARQL as one transaction}, label={lst:SPARQLtransactionUpdate},  captionpos={b}]
WITH <graphName> DELETE { ... } INSERT { ... } WHERE { ... }
\end{lstlisting}

We will remove all triples where the subject and predicate are the same. It means that if there was an array of triples, the whole collection would be removed, and a new single value would be added.