From 392c99f4a6d112ddb9c89d2f0a013ff7ce806935 Mon Sep 17 00:00:00 2001
From: Baptiste Toulemonde <toulemonde@cines.fr>
Date: Tue, 23 Aug 2022 10:38:36 +0200
Subject: [PATCH] WIP

---
 src/app/app-routing.module.ts                 |   6 +-
 src/app/app.module.ts                         |  88 ++++---
 src/app/datasets/datasets.component.ts        |   5 +-
 .../datasets/services/dataset-crud.service.ts |   8 +-
 src/app/mapping/class/requestMapping.ts       |   8 +-
 src/app/mapping/mapping.component.ts          | 240 +++++++++---------
 src/app/publishapi/class/keywordRequest.ts    |   9 +
 src/app/publishapi/publishapi.component.html  |  15 +-
 src/app/publishapi/publishapi.component.ts    |  79 ++++--
 .../semantic-enrichment.component.html        |  40 +++
 .../semantic-enrichment.component.scss        |   1 +
 .../semantic-enrichment.component.spec.ts     |  25 ++
 .../semantic-enrichment.component.ts          |  57 +++++
 .../services/post.service.spec.ts             |  16 ++
 .../services/post.service.ts                  |  23 ++
 src/environments/environment.ts               |   2 +-
 16 files changed, 425 insertions(+), 197 deletions(-)
 create mode 100644 src/app/publishapi/class/keywordRequest.ts
 create mode 100644 src/app/semantic-enrichment/semantic-enrichment.component.html
 create mode 100644 src/app/semantic-enrichment/semantic-enrichment.component.scss
 create mode 100644 src/app/semantic-enrichment/semantic-enrichment.component.spec.ts
 create mode 100644 src/app/semantic-enrichment/semantic-enrichment.component.ts
 create mode 100644 src/app/semantic-enrichment/services/post.service.spec.ts
 create mode 100644 src/app/semantic-enrichment/services/post.service.ts

diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts
index 61ed7455d..fb0727e4c 100644
--- a/src/app/app-routing.module.ts
+++ b/src/app/app-routing.module.ts
@@ -11,6 +11,7 @@ import { CallbackComponent } from './callback/callback.component';
 import { FdpGuard } from './authentication/services/fdp.guard';
 import { RepositoryinfoComponent } from './repositoryinfo/repositoryinfo.component';
 import { PublishApiComponent } from './publishapi/publishapi.component';
+import {SemanticEnrichmentComponent} from './semantic-enrichment/semantic-enrichment.component';
 
 export interface ICustomRoute extends Route {
   name?: string;
@@ -29,11 +30,12 @@ const routes: ICustomRoute[] = [
       ]
   },
   {path: 'fdpsignin', component: SignupComponent, canActivate: [AuthGuardService]},
-  { path: 'login', component: SigninComponent}
+  { path: 'login', component: SigninComponent},
+  { path: 'semantic', component: SemanticEnrichmentComponent}
 
 ]
 @NgModule({
   imports: [RouterModule.forRoot(routes)],
   exports: [RouterModule]
 })
-export class AppRoutingModule { }
\ No newline at end of file
+export class AppRoutingModule { }
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index c95b7f81c..67d2c4c18 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -44,6 +44,9 @@ import { NgProgressModule } from 'ngx-progressbar';
 import { NgProgressHttpModule } from 'ngx-progressbar/http';
 import { AuthHeaderInterceptor } from './authentication/interceptor/authHeader.interceptor';
 import { CallbackComponent } from './callback/callback.component';
+import { SemanticEnrichmentComponent } from './semantic-enrichment/semantic-enrichment.component';
+import {MatAutocompleteModule} from '@angular/material/autocomplete';
+import {MatFormFieldModule} from '@angular/material/form-field';
 
 
 
@@ -63,47 +66,52 @@ import { CallbackComponent } from './callback/callback.component';
     FeedbackDialogComponent,
     DatasetsDialogComponent,
     CallbackComponent,
-    
-  ],
-  imports: [
-    BrowserModule,
-    BrowserAnimationsModule,
-    MatMenuModule,
-    MatDividerModule,
-    MatCardModule,
-    MatInputModule,
-    MatDialogModule,
-    MatProgressSpinnerModule,
-    MatSelectModule,
-    MatSidenavModule,
-    FormsModule,
-    ReactiveFormsModule,
-    HttpClientModule,
-    FileSaverModule,
-    SearchModule,
-    AppRoutingModule,
-    AuthenticationModule,
-    NebularModule,
-    BrowserAnimationsModule,
-    NbThemeModule.forRoot({ name: 'default' }),
-    NbLayoutModule,
-    NbSpinnerModule,
-    NbSelectModule,
-    NbTabsetModule,
-    NbTooltipModule,
-    NbAutocompleteModule,
-    NbListModule,
-    NbAccordionModule,
-    NgProgressModule.withConfig({
-      
-      spinnerPosition: "left",
-      thick: true,
-      meteor: false
-    }),
-    NgProgressHttpModule,
-    NbToastrModule.forRoot(),
-    NbDialogModule.forRoot()
+    SemanticEnrichmentComponent,
+
   ],
+    imports: [
+        BrowserModule,
+        BrowserAnimationsModule,
+        MatMenuModule,
+        MatDividerModule,
+        MatCardModule,
+        MatInputModule,
+        MatDialogModule,
+        MatProgressSpinnerModule,
+        MatSelectModule,
+        MatSidenavModule,
+        FormsModule,
+        ReactiveFormsModule,
+        HttpClientModule,
+        FileSaverModule,
+        SearchModule,
+        AppRoutingModule,
+        AuthenticationModule,
+        NebularModule,
+        BrowserAnimationsModule,
+        NbThemeModule.forRoot({name: 'default'}),
+        NbLayoutModule,
+        NbSpinnerModule,
+        NbSelectModule,
+        NbTabsetModule,
+        NbTooltipModule,
+        NbAutocompleteModule,
+        NbListModule,
+        NbAccordionModule,
+        NgProgressModule.withConfig({
+
+            spinnerPosition: 'left',
+            thick: true,
+            meteor: false
+        }),
+        NgProgressHttpModule,
+        NbToastrModule.forRoot(),
+        NbDialogModule.forRoot(),
+        MatAutocompleteModule,
+        MatFormFieldModule,
+        MatInputModule,
+        ReactiveFormsModule
+    ],
   entryComponents: [DatasetsDialogComponent, FeedbackDialogComponent],
   providers: [
     AppConfiguration,
diff --git a/src/app/datasets/datasets.component.ts b/src/app/datasets/datasets.component.ts
index c22c9679a..ccd15ad1f 100644
--- a/src/app/datasets/datasets.component.ts
+++ b/src/app/datasets/datasets.component.ts
@@ -180,7 +180,7 @@ export class DatasetsComponent implements OnInit, AfterViewChecked, AfterContent
 
   }
 
-  async launchRequest(pathName: string, httpMethod: string, preview: boolean, datasetId?: number) {
+  async launchRequest(pathName: string, httpMethod: string, preview: boolean, datasetId?: string) {
     if (preview) {
       this.spinners.set(pathName, true);
     }
@@ -407,7 +407,7 @@ export class DatasetsComponent implements OnInit, AfterViewChecked, AfterContent
     }).finally(() => this.loading = false);
   }
 
-  private onCloseDatasetDialog(datasetRequestPathName: string, datasetRequestHttpMethod: string, datasetId: number[]) {
+  private onCloseDatasetDialog(datasetRequestPathName: string, datasetRequestHttpMethod: string, datasetId: string[]) {
     if (datasetId == null || datasetId.length === 0) {
       this.ready = false;
       return;
@@ -420,6 +420,7 @@ export class DatasetsComponent implements OnInit, AfterViewChecked, AfterContent
 
     for (let i = 0; i < datasetId.length; i++) {
       this.dataSetService.saveUrls(this.getUrls(datasetRequestPathName, datasetRequestHttpMethod, datasetId[i]), datasetId[i] );
+
       let requestPromise: Promise<void>;
       if (this.openApi.info['x-result'] !== 'xml') {
 
diff --git a/src/app/datasets/services/dataset-crud.service.ts b/src/app/datasets/services/dataset-crud.service.ts
index 08181e6e5..b9cb55b1a 100644
--- a/src/app/datasets/services/dataset-crud.service.ts
+++ b/src/app/datasets/services/dataset-crud.service.ts
@@ -19,9 +19,9 @@ export class DatasetCrudService {
   smartHarvesterToken = this.sessionStorage.getToken();
   public results: string[] = [];
   itemsDataset: Object[] = [];
-  ids: number[] = [];
+  ids: string[] = [];
   urls: Object[] = [];
-  idsUrls: number[] = []
+  idsUrls: string[] = [];
 
   constructor(
     private http: HttpClient,
@@ -152,7 +152,7 @@ export class DatasetCrudService {
   getLocally<T = any>(path: string): Observable<T> {
     return this.http.get<T>(`${path}`);
   }
-  saveDatasets(obj: Object, id: number) {
+  saveDatasets(obj: Object, id: string) {
     this.itemsDataset.push(obj);
     this.ids.push(id);
   }
@@ -161,7 +161,7 @@ export class DatasetCrudService {
     this.ids = [];
   }
 
-  saveUrls(url: Object, id: number) {
+  saveUrls(url: Object, id: string) {
     this.urls.push(url);
     this.idsUrls.push(id);
   }
diff --git a/src/app/mapping/class/requestMapping.ts b/src/app/mapping/class/requestMapping.ts
index 1ee7bfc81..5bb9c1886 100644
--- a/src/app/mapping/class/requestMapping.ts
+++ b/src/app/mapping/class/requestMapping.ts
@@ -1,10 +1,10 @@
 export class RequestMapping {
-    urls: string[];
+    ids: string[];
     paths: Path[];
     fdpToken: string;
 
-    constructor (urls: string[], paths: Path[], fdpToken: string) {
-        this.urls = urls;
+    constructor (ids: string[], paths: Path[], fdpToken: string) {
+        this.ids = ids;
         this.paths = paths;
         this.fdpToken = fdpToken;
     }
@@ -27,4 +27,4 @@ export class Path {
 export class ResponseMapping {
     notPublishedUrl: string[];
     publishedUrl: string[];
-}
\ No newline at end of file
+}
diff --git a/src/app/mapping/mapping.component.ts b/src/app/mapping/mapping.component.ts
index 152445461..a25b4f5c4 100644
--- a/src/app/mapping/mapping.component.ts
+++ b/src/app/mapping/mapping.component.ts
@@ -1,7 +1,7 @@
 
 
 import { HttpResponse } from '@angular/common/http';
-import { ChangeDetectorRef, Component, Input, OnInit, ViewChild } from '@angular/core';
+import {ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, ViewChild} from '@angular/core';
 import { MatDialog } from '@angular/material/dialog';
 import { Router } from '@angular/router';
 
@@ -25,11 +25,18 @@ import { JSONPath } from 'jsonpath-plus';
 })
 export class MappingComponent implements OnInit {
 
-  addDistribution = false
+  @Output()
+  pathsEvent = new EventEmitter<Path[]>();
+
+  @Output()
+  isJsonPathEvent = new EventEmitter();
+
+  paths: Path[];
+  addDistribution = false;
   check = false;
   distributions: Property[] = [];
   ontology: string;
-  itemsdataset: any[] = []
+  itemsdataset: any[] = [];
   urls: any[] = [];
   datasets: Property[];
   vocabularies: Property[];
@@ -39,12 +46,12 @@ export class MappingComponent implements OnInit {
   distributionSelectedPaths: string[];
   datasetMappedMetadatas: Array<Array<Map<number, string>>>;
   distributionMappedMetadatas: Array<Array<Map<number, string>>>;
-  index: number = 0
-  first: boolean = true;
+  index = 0;
+  first = true;
   loading = false;
   loadingCr = false;
   FDP_URL = environment.fdpUrl;
-  ids: number[];
+  ids: string[];
   default = true;
   isJsonPath = false;
   @ViewChild('autoInput') input;
@@ -59,15 +66,15 @@ export class MappingComponent implements OnInit {
   }
 
   ngOnInit() {
-    console.log(this.type)
+    console.log(this.type);
     this.urls = this.dataSetService.urls;
     console.table(this.urls);
     this.ids = this.dataSetService.idsUrls;
-    if (this.type !== "ISO 19115") {
+    if (this.type !== 'ISO 19115') {
       this.urls = this.dataSetService.urls;
       this.ids = this.dataSetService.idsUrls;
       this.itemsdataset = this.dataSetService.itemsDataset;
-      console.log(this.itemsdataset)
+      console.log(this.itemsdataset);
       this.ids = this.dataSetService.ids;
       this.keys = [];
       this.getKeysFromMetadataCustom(this.itemsdataset[0], '');
@@ -82,15 +89,15 @@ export class MappingComponent implements OnInit {
   selectOntology(): void {
     this.dataSetService.getLocally(`./assets/geodcat.json`).subscribe(
       datasets => {
-        this.datasets = this.ontology === "dcat" ? datasets.filter(d => !d.geodcat) : datasets;
-        this.vocabularies = this.ontology === "dcat" ? datasets.filter(d => !d.geodcat) : datasets;
+        this.datasets = this.ontology === 'dcat' ? datasets.filter(d => !d.geodcat) : datasets;
+        this.vocabularies = this.ontology === 'dcat' ? datasets.filter(d => !d.geodcat) : datasets;
         this.vocabularies.forEach(dataset => dataset.dcatClass = 'dcat:dataset');
         this.selectedPaths = [];
         this.dataSetService.getLocally('./assets/distribution.json').subscribe(
           (distributions: Distribution[]) => {
-            this.distributions = this.ontology === "dcat" ? distributions.filter(d => !d.geodcat) : distributions;
+            this.distributions = this.ontology === 'dcat' ? distributions.filter(d => !d.geodcat) : distributions;
             this.distributions.forEach(distribution => distribution.dcatClass = 'dcat:distribution');
-            this.vocabularies = this.vocabularies.concat(this.ontology === "dcat" ? this.distributions.filter(d => !d.geodcat) : distributions);
+            this.vocabularies = this.vocabularies.concat(this.ontology === 'dcat' ? this.distributions.filter(d => !d.geodcat) : distributions);
             this.distributionSelectedPaths = [];
           }
         );
@@ -106,9 +113,9 @@ export class MappingComponent implements OnInit {
   mapFromXslt() {
     this.loading = true;
     this.itemsdataset = [];
-    let requestPromises: Promise<any>[] = [];
+    const requestPromises: Promise<any>[] = [];
     this.urls.forEach((url: string) => {
-      let requestPromise = this.dataSetService.getDcatFromApi(this.catalogId, url)
+      const requestPromise = this.dataSetService.getDcatFromApi(this.catalogId, url)
         .then((response: Response) => {
           response.text()
             .then((text) => {
@@ -122,11 +129,11 @@ export class MappingComponent implements OnInit {
 
 
   createDataset(item: Object, classDcat: string): Map<number, string> {
-    let mappedMetadata: Map<number, string> = new Map()
-    const array: string[] = (classDcat === "dataset") ? this.selectedPaths : this.distributionSelectedPaths;
+    const mappedMetadata: Map<number, string> = new Map();
+    const array: string[] = (classDcat === 'dataset') ? this.selectedPaths : this.distributionSelectedPaths;
     for (let i = 0; i < array.length; i++) {
       if (array[i] && array.length > 0) {
-        let tab = array[i].split(' : ');
+        const tab = array[i].split(' : ');
         !this.isJsonPath ? mappedMetadata.set(i, this.getValueCustom(tab, item)) : mappedMetadata.set(i, this.getValueJsonPath(array[i], item));
       }
     }
@@ -135,7 +142,7 @@ export class MappingComponent implements OnInit {
   }
 
   publishDataset(): void {
-    let paths: Path[] = [];
+    const paths: Path[] = [];
 
     for (let i = 0; i < this.datasets.length; i++) {
       if (this.selectedPaths[i]) {
@@ -144,19 +151,23 @@ export class MappingComponent implements OnInit {
     }
     for (let i = 0; i < this.distributions.length; i++) {
       if (this.distributionSelectedPaths[i]) {
-        paths.push(new Path(this.distributions[i].uri, this.distributionSelectedPaths[i], this.distributions[i].card, this.distributions[i].dcatClass));
+        paths.push(
+          new Path(
+            this.distributions[i].uri, this.distributionSelectedPaths[i], this.distributions[i].card, this.distributions[i].dcatClass
+          )
+        );
       }
     }
 
+    this.pathsEvent.emit(paths);
+    const data: RequestMapping = new RequestMapping(this.urls, paths, this.tokenStorage.getFDPToken());
 
-    let data: RequestMapping = new RequestMapping(this.urls, paths, this.tokenStorage.getFDPToken());
-
-    let postedDatasets = [];
-    let notPostedDatasets = [];
+    const postedDatasets = [];
+    const notPostedDatasets = [];
     this.loading = true;
     const requestPromises: Promise<any>[] = [];
 
-    let requestPromise = this.mappingService.postToFdpFropSmartharvester(this.catalogId, data, this.isJsonPath).then(resp => {
+    const requestPromise = this.mappingService.postToFdpFropSmartharvester(this.catalogId, data, this.isJsonPath).then(resp => {
       if (resp) {
         console.log(resp);
         resp.json().then((datas: any) => {
@@ -177,14 +188,14 @@ export class MappingComponent implements OnInit {
         }
       }).afterClosed().subscribe();
 
-    })
+    });
   }
 
   buildRDF(vocabularies: Property[], array: Map<number, string>[], i: number): string {
-    let properties = "";
+    let properties = '';
     let version = false;
     array[i].forEach((value: string, key: number) => {
-      let uri = vocabularies[key].uri;
+      const uri = vocabularies[key].uri;
       if (uri === 'dct:hasVersion') {
         version = true;
       }
@@ -193,7 +204,7 @@ export class MappingComponent implements OnInit {
         if (this.isReplicable(this.getCard(uri))) {
           value.forEach(v => {
             properties += this.writeRdf(uri, v);
-          })
+          });
         } else {
           properties += this.writeRdf(uri, value[0]);
         }
@@ -201,21 +212,21 @@ export class MappingComponent implements OnInit {
         properties += this.writeRdf(uri, value);
       }
 
-    })
+    });
 
-    if (!version) properties += `dct:hasVersion "undefined";\n`;
+    if (!version) { properties += `dct:hasVersion "undefined";\n`; }
 
     return properties;
   }
 
   publishDatasetFromGeodcatApi() {
-    let postedDatastes = [];
-    let notPostedDatasets = [];
+    const postedDatastes = [];
+    const notPostedDatasets = [];
     this.loading = true;
     const requestPromises: Promise<any>[] = [];
     for (let i = 0; i < this.urls.length; i++) {
 
-      let requestPromise = this.dataSetService.createDatasetXml(this.itemsdataset[i]).then((resp: HttpResponse<any>) => {
+      const requestPromise = this.dataSetService.createDatasetXml(this.itemsdataset[i]).then((resp: HttpResponse<any>) => {
         if (resp.status.toString().startsWith('2')) {
           const location: string = resp.headers.get('location');
           console.log(location);
@@ -224,7 +235,7 @@ export class MappingComponent implements OnInit {
         } else {
           notPostedDatasets.push(this.ids[i]);
         }
-      })
+      });
       requestPromises.push(requestPromise);
     }
     Promise.all(requestPromises).finally(() => {
@@ -236,15 +247,15 @@ export class MappingComponent implements OnInit {
         }
       }).afterClosed().subscribe();
 
-    })
+    });
   }
 
 
 
 
   private writeRdf(key: string, value: string): string {
-    let properties = "";
-    value = (value && typeof value === "string") ? value.replace(/\n/g, '') : value;
+    let properties = '';
+    value = (value && typeof value === 'string') ? value.replace(/\n/g, '') : value;
 
     switch (key) {
       case 'dcat:landingPage':
@@ -276,14 +287,14 @@ export class MappingComponent implements OnInit {
             if (typeof e === 'object') {
               Object.keys(e).forEach(k => {
                 this.keys.push(keyParent + k);
-              })
+              });
               this.getKeysFromMetadataCustom(e, keyParent + key + ' : ');
             }
           });
-          this.keys.push(keyParent + key)
+          this.keys.push(keyParent + key);
           this.getKeysFromMetadataCustom(obj[key], keyParent + key + ' : ');
         } else {
-          this.keys.push(keyParent + key)
+          this.keys.push(keyParent + key);
           this.getKeysFromMetadataCustom(obj[key], keyParent + key + ' : ');
         }
       } else {
@@ -301,15 +312,15 @@ export class MappingComponent implements OnInit {
       if (typeof obj[key] === 'object') {
         if (Array.isArray(obj[key])) {
           if (keyParent) {
-            this.keys.push(keyParent + ' : ' + key)
+            this.keys.push(keyParent + ' : ' + key);
           } else {
-            this.keys.push(key)
+            this.keys.push(key);
           }
           obj[key].forEach(e => {
             if (typeof e === 'object') {
               this.getKeysFromMetadataDataverse(e, keyParent + ' : ' + key + ' : ' + obj[key].indexOf(e));
             } else {
-              this.keys.push(keyParent + ' : ' + key + ' : ' + obj[key].indexOf(e))
+              this.keys.push(keyParent + ' : ' + key + ' : ' + obj[key].indexOf(e));
             }
           });
         } else {
@@ -321,9 +332,9 @@ export class MappingComponent implements OnInit {
         }
       } else {
         if (keyParent) {
-          this.keys.push(keyParent + ' : ' + key)
+          this.keys.push(keyParent + ' : ' + key);
         } else {
-          this.keys.push(key)
+          this.keys.push(key);
         }
       }
     });
@@ -332,10 +343,10 @@ export class MappingComponent implements OnInit {
     let value = JSONPath({
       path: jsonPath,
       json: item
-    })
+    });
 
-    if (value === null || value === "") {
-      value = "undefined";
+    if (value === null || value === '') {
+      value = 'undefined';
     }
 
     return value;
@@ -348,12 +359,12 @@ export class MappingComponent implements OnInit {
       } else {
         for (let i = 0; i < tab.length; i++) {
           if (i == 0) {
-            obj = item[tab[i]]
+            obj = item[tab[i]];
           } else if (i < tab.length - 1 && obj[tab[i]]) {
             obj = obj[tab[i]];
           } else {
             if (Array.isArray(obj) && obj.some(e => typeof e === 'object')) {
-              let array = [];
+              const array = [];
               obj.forEach(e => {
                 if (e[tab[i]]) {
                   array.push(e[tab[i]]);
@@ -361,13 +372,13 @@ export class MappingComponent implements OnInit {
               });
               return array;
             } else if (typeof obj === 'object' && Object.values(obj).every(e => Array.isArray(e))) {
-              let array = [];
-              for (let element in obj) {
+              const array = [];
+              for (const element in obj) {
                 obj[element].forEach(e => {
                   if (e[tab[i]]) {
                     array.push(e[tab[i]]);
                   }
-                })
+                });
               }
               return array;
             } else if (Array.isArray(obj[tab[i]])) {
@@ -379,17 +390,17 @@ export class MappingComponent implements OnInit {
         }
       }
     } catch {
-      return "undefined"
+      return 'undefined';
     }
-    
-   
+
+
 
   }
   private getDistributionItem(tab: string[], item: Object) {
     if (tab.length === 0) {
       return [];
     }
-    let currentPath = tab[0];
+    const currentPath = tab[0];
     if (!item.hasOwnProperty(currentPath) || item[currentPath] == null) {
       return [];
     }
@@ -403,13 +414,13 @@ export class MappingComponent implements OnInit {
   }
 
   private getValueDataverse(tab: string[], item: Object): string {
-    let obj: Object 
+    let obj: Object;
     for (let i = 0; i < tab.length; i++) {
       if (tab.length == 1) {
         return item[tab[0]];
       } else {
         if (i == 0) {
-          obj = item[tab[i]]
+          obj = item[tab[i]];
         } else if (i < tab.length - 1 && obj[tab[i]]) {
           obj = obj[tab[i]];
         } else {
@@ -417,17 +428,17 @@ export class MappingComponent implements OnInit {
             return obj[tab[i]];
           } else {
             if (i == tab.length - 2) {
-              this.getKeysFromMetadataDataverse(item, "");
-              console.log(tab[i] + "  " + i)
+              this.getKeysFromMetadataDataverse(item, '');
+              console.log(tab[i] + '  ' + i);
               this.keys.forEach(k => {
-                let table = k.split(" : ");
+                const table = k.split(' : ');
                 if (table[table.length - 2] === tab[i]) {
                   for (let i = 0; i < tab.length; i++) {
                     if (table.length == 1) {
                       return item[tab[0]];
                     } else {
                       if (i == 0) {
-                        obj = item[table[i]]
+                        obj = item[table[i]];
                       } else if (i < table.length - 1 && obj[table[i]]) {
                         obj = obj[table[i]];
                       } else {
@@ -440,7 +451,7 @@ export class MappingComponent implements OnInit {
                     }
                   }
                 }
-              })
+              });
             }
           }
         }
@@ -455,44 +466,44 @@ export class MappingComponent implements OnInit {
   mapDataset() {
     this.loadingCr = true;
     this.datasetMappedMetadatas = new Array<Array<Map<number, string>>>();
-    this.distributionMappedMetadatas = new Array<Array<Map<number, string>>>()
+    this.distributionMappedMetadatas = new Array<Array<Map<number, string>>>();
     for (let i = 0; i < this.itemsdataset.length; i++) {
-      this.datasetMappedMetadatas.push([this.createDataset(this.itemsdataset[i], "dataset")]);
+      this.datasetMappedMetadatas.push([this.createDataset(this.itemsdataset[i], 'dataset')]);
       if (this.distributionSelectedPaths.length > 0) {
         if (this.distributionSelectedPaths[0] !== '' && this.distributionSelectedPaths[0] !== null && this.distributionSelectedPaths[0]) {
-          let distributionItems: Object[] = (this.isJsonPath) ? this.getValueJsonPath(this.distributionSelectedPaths[0], this.itemsdataset[i]) : this.getDistributionItem(this.distributionSelectedPaths[0].split(' : '), this.itemsdataset[i]);
-          let distributionArray: Map<number, string>[] = []
+          const distributionItems: Object[] = (this.isJsonPath) ? this.getValueJsonPath(this.distributionSelectedPaths[0], this.itemsdataset[i]) : this.getDistributionItem(this.distributionSelectedPaths[0].split(' : '), this.itemsdataset[i]);
+          const distributionArray: Map<number, string>[] = [];
           for (let j = 0; j < distributionItems.length; j++) {
-            let item = distributionItems[j]
-            distributionArray.push(this.createDataset(distributionItems[j], "distribution"));
+            const item = distributionItems[j];
+            distributionArray.push(this.createDataset(distributionItems[j], 'distribution'));
           }
           this.distributionMappedMetadatas.push(distributionArray);
         } else {
-          this.distributionMappedMetadatas.push([this.createDataset(this.itemsdataset[i], "distribution")])
+          this.distributionMappedMetadatas.push([this.createDataset(this.itemsdataset[i], 'distribution')]);
         }
       }
     }
     this.first = false;
   }
   next() {
-    //this.loadingCr = true;  
+    // this.loadingCr = true;
     if (this.index < this.itemsdataset.length) {
       this.index += 1;
-      //this.createDataset(this.itemsdataset[this.index])
+      // this.createDataset(this.itemsdataset[this.index])
       console.log('index = ' + this.index);
     }
   }
   prev() {
-    //this.loadingCr = true;
+    // this.loadingCr = true;
     if (this.index > 0) {
       this.index -= 1;
     }
-    //this.createDataset(this.itemsdataset[this.index])
+    // this.createDataset(this.itemsdataset[this.index])
     console.log('index = ' + this.index);
   }
 
   createObjectToExport(): DatasetPath[] {
-    let datasetPathArray: DatasetPath[] = []
+    const datasetPathArray: DatasetPath[] = [];
     for (let i = 0; i < this.datasets.length; i++) {
       if (this.selectedPaths[i]) {
         datasetPathArray.push(new DatasetPath(this.datasets[i], this.selectedPaths[i], 'dcat:dataset', this.datasets[i].card));
@@ -500,7 +511,7 @@ export class MappingComponent implements OnInit {
     }
     for (let i = 0; i < this.distributions.length; i++) {
       if (this.distributionSelectedPaths[i]) {
-        datasetPathArray.push(new DatasetPath(this.distributions[i], this.distributionSelectedPaths[i], 'dcat:distribution', this.distributions[i].card))
+        datasetPathArray.push(new DatasetPath(this.distributions[i], this.distributionSelectedPaths[i], 'dcat:distribution', this.distributions[i].card));
       }
     }
     return datasetPathArray;
@@ -508,7 +519,7 @@ export class MappingComponent implements OnInit {
 
   downloadJson() {
 
-    let datasetPathArray = this.createObjectToExport();
+    const datasetPathArray = this.createObjectToExport();
 
 
 
@@ -544,57 +555,57 @@ export class MappingComponent implements OnInit {
     this.selectedPaths  = [];
     this.distributionSelectedPaths = [];
     reader.onloadend = () => {
-      if (jsonFile.name.split('.')[1] === "tsv") {
-        let paths: ResponseFileTsv[] = <ResponseFileTsv[]>this.mappingService.tsvToJson(reader.result as string);
-        let datasetPath: ResponseFileTsv[] = [];
-        let distributionPath: ResponseFileTsv[] = [];
-        console.table(paths)
+      if (jsonFile.name.split('.')[1] === 'tsv') {
+        const paths: ResponseFileTsv[] = this.mappingService.tsvToJson(reader.result as string) as ResponseFileTsv[];
+        const datasetPath: ResponseFileTsv[] = [];
+        const distributionPath: ResponseFileTsv[] = [];
+        console.table(paths);
         paths.forEach(path => {
           (path.object_category.includes('dcat:dataset')) ? datasetPath.push(path) : distributionPath.push(path);
-        })
+        });
 
-        console.log(datasetPath)
-        console.log(distributionPath)
-        if (distributionPath.length > 0) this.addDistribution = true;
+        console.log(datasetPath);
+        console.log(distributionPath);
+        if (distributionPath.length > 0) { this.addDistribution = true; }
         this.fillFromTsv(this.datasets, this.selectedPaths, datasetPath, 'dcat:dataset');
         this.fillFromTsv(this.distributions, this.distributionSelectedPaths, distributionPath, 'dcat:distribution');
       } else {
-        let paths: DatasetPath[] = <DatasetPath[]>JSON.parse(reader.result as string);
-        console.table(paths)
+        const paths: DatasetPath[] = JSON.parse(reader.result as string) as DatasetPath[];
+        console.table(paths);
 
         for (let i = 0; i < paths.length; i++) {
           if (i > 0 && paths[i].dcatProperty === paths[i - 1].dcatProperty) {
-            const voc: Property = this.datasets.find(e => e.uri === (<Property>paths[i].dcatProperty).uri);
+            const voc: Property = this.datasets.find(e => e.uri === (paths[i].dcatProperty as Property).uri);
             this.datasets.splice(i + 1, 0, voc);
             this.selectedPaths.splice(i + 1, 0, paths[i].path);
 
             if (typeof paths[i].dcatProperty !== 'object') {
-              this.datasets[i] = this.vocabularies.filter(e => e.dcatClass === 'dcat:dataset').find(v => v.uri === <string>paths[i].dcatProperty);
+              this.datasets[i] = this.vocabularies.filter(e => e.dcatClass === 'dcat:dataset').find(v => v.uri === paths[i].dcatProperty as string);
             } else {
-              this.datasets[i] = this.vocabularies.filter(e => e.dcatClass === 'dcat:dataset').find(v => v.uri === (<OldProperty><unknown>paths[i].dcatProperty).identifier);
+              this.datasets[i] = this.vocabularies.filter(e => e.dcatClass === 'dcat:dataset').find(v => v.uri === (paths[i].dcatProperty as unknown as OldProperty).identifier);
             }
 
           } else {
             this.selectedPaths[i] = paths[i].path;
             if (typeof paths[i].dcatProperty !== 'object') {
-              this.datasets[i] = this.vocabularies.find(v => v.uri === <string>paths[i].dcatProperty);
+              this.datasets[i] = this.vocabularies.find(v => v.uri === paths[i].dcatProperty as string);
             } else {
-              this.datasets[i] = this.vocabularies.find(v => v.uri === (<OldProperty><unknown>paths[i].dcatProperty).identifier);
+              this.datasets[i] = this.vocabularies.find(v => v.uri === (paths[i].dcatProperty as unknown as OldProperty).identifier);
             }
           }
 
 
         }
       }
-    }
+    };
     reader.readAsText(jsonFile);
-    this.ref.markForCheck()
+    this.ref.markForCheck();
 
 
   }
 
   addField(index: number, properties: Property[], paths: string[]) {
-    let addedDcat: Property = properties.find(e => e.uri === properties[index].uri);
+    const addedDcat: Property = properties.find(e => e.uri === properties[index].uri);
     properties.splice(index + 1, 0, addedDcat);
 
     paths.splice(index + 1, 0, '');
@@ -619,7 +630,7 @@ export class MappingComponent implements OnInit {
   /* autocompletion functions */
 
   private filter(value: string): string[] {
-    let filterValue = value.toLowerCase();
+    const filterValue = value.toLowerCase();
     return this.keys.filter(optionValue => optionValue.toLowerCase().includes(filterValue));
   }
 
@@ -629,10 +640,10 @@ export class MappingComponent implements OnInit {
     );
   }
   onModelChange(value: string) {
-    if (!this.isJsonPath) this.filteredOptions = of(this.filter(value));
+    if (!this.isJsonPath) { this.filteredOptions = of(this.filter(value)); }
   }
   reset() {
-    if (!this.isJsonPath) this.filteredOptions = of(this.keys);
+    if (!this.isJsonPath) { this.filteredOptions = of(this.keys); }
   }
 
   toggle(checked: boolean) {
@@ -641,7 +652,8 @@ export class MappingComponent implements OnInit {
 
   toggleJsonPath(checked: boolean) {
     this.isJsonPath = checked;
-    if (this.isJsonPath) this.filteredOptions = of([]);
+    if (this.isJsonPath) { this.filteredOptions = of([]); }
+    this.isJsonPathEvent.emit(this.isJsonPath);
   }
 
   toggleDistri(checked: boolean) {
@@ -649,11 +661,11 @@ export class MappingComponent implements OnInit {
   }
 
   isMandatory(card: string): boolean {
-    return card.startsWith("1");
+    return card.startsWith('1');
   }
 
   isReplicable(card: string): boolean {
-    return card.endsWith("n");
+    return card.endsWith('n');
   }
 
   getCard(uri: string): string {
@@ -666,17 +678,17 @@ export class MappingComponent implements OnInit {
     @prefix adms: <http://www.w3.org/ns/adms#> .
     @prefix dqv:  <http://www.w3.org/ns/dqv#> .
     @prefix geodcat: <http://data.europa.eu/930/>.
-    @prefix prov: <http://www.w3.org/ns/prov#>. 
-    @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>. 
-    @prefix skos: <http://www.w3.org/2004/02/skos/core#>. 
-    @prefix spdx:  <http://spdx.org/rdf/terms#>. 
-    @prefix foaf: <http://xmlns.com/foaf/0.1/>. 
-    @prefix odrl: <http://www.w3.org/ns/odrl/2/>. 
+    @prefix prov: <http://www.w3.org/ns/prov#>.
+    @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
+    @prefix skos: <http://www.w3.org/2004/02/skos/core#>.
+    @prefix spdx:  <http://spdx.org/rdf/terms#>.
+    @prefix foaf: <http://xmlns.com/foaf/0.1/>.
+    @prefix odrl: <http://www.w3.org/ns/odrl/2/>.
     @prefix cnt:   <http://www.w3.org/2011/content#>.
     @prefix language: <http://id.loc.gov/vocabulary/iso639-1/>.
     @prefix s: <${this.FDP_URL}/>.
     @prefix c: <${this.FDP_URL}/dataset/>.
-    
+
     s:new
     a dcat:Distribution, dcat:Resource;
     dct:isPartOf c:${datasetId};
@@ -689,12 +701,12 @@ export class MappingComponent implements OnInit {
     @prefix adms: <http://www.w3.org/ns/adms#> .
     @prefix dqv:  <http://www.w3.org/ns/dqv#> .
     @prefix geodcat: <http://data.europa.eu/930/>.
-    @prefix prov: <http://www.w3.org/ns/prov#>. 
-    @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>. 
+    @prefix prov: <http://www.w3.org/ns/prov#>.
+    @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
     @prefix language: <http://id.loc.gov/vocabulary/iso639-1/>.
     @prefix s: <${this.FDP_URL}/>.
     @prefix c: <${this.FDP_URL}/catalog/>.
-    
+
     s:new
     a dcat:Dataset, dcat:Resource;
     dct:isPartOf c:${this.catalogId} ;
diff --git a/src/app/publishapi/class/keywordRequest.ts b/src/app/publishapi/class/keywordRequest.ts
new file mode 100644
index 000000000..1d6d00608
--- /dev/null
+++ b/src/app/publishapi/class/keywordRequest.ts
@@ -0,0 +1,9 @@
+export class KeywordRequest {
+  isJsonPAth: boolean;
+  keywordPaths: string [];
+
+  constructor(isJsonPath: boolean, keywordPaths: string []) {
+    this.isJsonPAth = isJsonPath;
+    this.keywordPaths = keywordPaths;
+  }
+}
diff --git a/src/app/publishapi/publishapi.component.html b/src/app/publishapi/publishapi.component.html
index d11d5b486..ed5330bb2 100644
--- a/src/app/publishapi/publishapi.component.html
+++ b/src/app/publishapi/publishapi.component.html
@@ -315,21 +315,20 @@
         <p class="lorem">
           Map your metadata schema with DCAT schema
         </p>
-        <app-mapping *ngIf="initLabelThree && datasets.ready" [catalogId]="openApi.info['x-catalog-id']" [type]="openApi.info['x-format']">
+        <app-mapping *ngIf="initLabelThree && datasets.ready" [catalogId]="openApi.info['x-catalog-id']" [type]="openApi.info['x-format']"
+        (pathsEvent)="pathsEventHandler($event)" (isJsonPathEvent)="isJsonPathEventHandler($event)">
         </app-mapping>
         <button class="prev-button" nbButton nbStepperPrevious
-          (click)="initLabelThree=false;  resetDataset(); datasets.ready = false">prev</button>
+          (click)="initLabelThree=false;  resetDataset(); datasets.ready = false"; getKeywords()>prev</button>
         <button class="next-button" nbButton disabled nbStepperNext>next</button>
       </nb-step>
-      <!--<nb-step [label]="labelFour">
+      <nb-step [label]="labelFour">
         <ng-template #labelFour>Fourth step</ng-template>
-        <h4>Populate FDP</h4>
-        <p class="lorem">
-          Populate FDP with datasets metadata
-        </p>
+        <h4>Semantic Enrichment</h4>
+        <app-semantic-enrichment [paths]="paths"></app-semantic-enrichment>
         <button class="prev-button" nbButton nbStepperPrevious>prev</button>
         <button class="next-button" nbButton disabled nbStepperNext>next</button>
-      </nb-step>-->
+      </nb-step>
     </nb-stepper>
   </nb-card-body>
 </nb-card>
diff --git a/src/app/publishapi/publishapi.component.ts b/src/app/publishapi/publishapi.component.ts
index 5caf7af56..0e894729c 100644
--- a/src/app/publishapi/publishapi.component.ts
+++ b/src/app/publishapi/publishapi.component.ts
@@ -5,11 +5,13 @@ import { cloneDeep } from 'lodash';
 import { DatasetCrudService } from '../datasets/services/dataset-crud.service';
 import { CatalogService, FdpApiResponseItem } from '../services/catalog.service';
 import HttpStatusCode from './class/http-enum';
-import { OpenApi, Parameter, Path, Request, Response } from './class/openapi';
+import {OpenApi, Parameter, Path, Request, Response} from './class/openapi';
 import { OpenApiTag } from './class/openapi-dto';
 import { ParameterType, ShemaType } from './class/openapi-enum';
 import { OpenApiDTOMappingService } from './services/openapi-dto-mapping-service';
 import { OpenApiService } from './services/openapi-service';
+import {Path as PathReq} from '../mapping/class/requestMapping' ;
+import {KeywordRequest} from './class/keywordRequest';
 
 @Component({
   selector: 'app-publishapi',
@@ -23,6 +25,9 @@ export class PublishApiComponent implements OnInit {
   @ViewChild('datasets') datasets;
   @ViewChild('stepper') stepper: NbStepperComponent;
 
+  paths: PathReq[];
+  isJsonPath: boolean;
+
   constructor(
     private openApiService: OpenApiService,
     private catalogService: CatalogService,
@@ -34,7 +39,15 @@ export class PublishApiComponent implements OnInit {
   parametersTypes: string[];
   shemaTypes: string[];
   httpStatusCodes: string[];
-  catalogList: { title: string, catId: string, server: string, type: string, version?: string, description?: string, result?: string}[] = [];
+  catalogList: {
+    title: string,
+    catId: string,
+    server: string,
+    type: string,
+    version?: string,
+    description?: string,
+    result?: string
+  }[] = [];
   canNext = false;
   type: string;
   initLabelThree = false;
@@ -43,12 +56,20 @@ export class PublishApiComponent implements OnInit {
     this.openApi = new OpenApi(null, null);
     this.parametersTypes = Object.keys(ParameterType);
     this.shemaTypes = Object.keys(ShemaType);
-    const httpStatusCodeskeys = Object.keys(HttpStatusCode).filter(k => typeof HttpStatusCode[k as any] === "number");
+    const httpStatusCodeskeys = Object.keys(HttpStatusCode).filter(k => typeof HttpStatusCode[k as any] === 'number');
     this.httpStatusCodes = httpStatusCodeskeys.map(k => HttpStatusCode[k as any]);
     this.initCatalogList();
     this.datasetService.resetDataset();
   }
 
+  pathsEventHandler($event: PathReq[]) {
+    this.paths = $event;
+  }
+
+  isJsonPathEventHandler($event: boolean) {
+    this.isJsonPath = $event;
+  }
+
   getPrettyJson(): string {
     return this.openApiService.getPrettyJson(this.openApi);
   }
@@ -59,7 +80,7 @@ export class PublishApiComponent implements OnInit {
         const titlePromises: Promise<any>[] = [];
         response.forEach((catalog) => {
           titlePromises.push(
-            
+
             this.catalogService.getCatalogContentById(catalog.catId).toPromise().then(
               (response2) => {
                 this.catalogList.push({
@@ -107,9 +128,9 @@ export class PublishApiComponent implements OnInit {
       error: () => {
         this.openApi = new OpenApi(catId, this.getServer(catId));
         this.openApi.info['x-format'] = this.getType(catId);
-        this.openApi.info['title'] = this.getTitle(catId);
-        this.openApi.info['version'] = this.getVersion(catId);
-        this.openApi.info['description'] = this.getDescription(catId);
+        this.openApi.info.title = this.getTitle(catId);
+        this.openApi.info.version = this.getVersion(catId);
+        this.openApi.info.description = this.getDescription(catId);
         this.openApi.info['x-result'] = this.getResult(catId);
         this.openApi.paths.push(this.openApiDTOMappingService.getEmptyPath(OpenApiTag.search));
         this.openApi.paths.push(this.openApiDTOMappingService.getEmptyPath(OpenApiTag.dataset));
@@ -176,11 +197,11 @@ export class PublishApiComponent implements OnInit {
       }
     }
     return null;
-  } 
+  }
 
   getType(catId: string): string {
     for (const catalog of this.catalogList) {
-      if(catalog.catId === catId) {
+      if (catalog.catId === catId) {
         return catalog.type;
       }
     }
@@ -189,7 +210,7 @@ export class PublishApiComponent implements OnInit {
 
   getTitle(catId: string): string {
     for (const catalog of this.catalogList) {
-      if(catalog.catId === catId) {
+      if (catalog.catId === catId) {
         return catalog.title;
       }
     }
@@ -198,7 +219,7 @@ export class PublishApiComponent implements OnInit {
 
   getVersion(catId: string): string {
     for (const catalog of this.catalogList) {
-      if(catalog.catId === catId) {
+      if (catalog.catId === catId) {
         return catalog.version;
       }
     }
@@ -207,7 +228,7 @@ export class PublishApiComponent implements OnInit {
 
   getDescription(catId: string): string {
     for (const catalog of this.catalogList) {
-      if(catalog.catId === catId) {
+      if (catalog.catId === catId) {
         return catalog.description;
       }
     }
@@ -216,8 +237,8 @@ export class PublishApiComponent implements OnInit {
 
   getResult(catId: string): string {
     for (const catalog of this.catalogList) {
-      if(catalog.catId === catId) {
-        return (catalog.type === "ISO 19115") ? 'xml' : 'json';
+      if (catalog.catId === catId) {
+        return (catalog.type === 'ISO 19115') ? 'xml' : 'json';
       }
     }
     return null;
@@ -228,15 +249,15 @@ export class PublishApiComponent implements OnInit {
   }
 
   selectAllJson(): void {
-    var range = document.createRange();
+    const range = document.createRange();
     range.selectNodeContents(document.getElementById('json'));
-    var sel = window.getSelection();
+    const sel = window.getSelection();
     sel.removeAllRanges();
     sel.addRange(range);
   }
 
   downloadJson(): void {
-    let windowVar: any =  window.navigator;
+    const windowVar: any =  window.navigator;
     const newBlob = new Blob([this.openApiService.getPrettyJson(this.openApi)], { type: 'application/json' });
     if (windowVar && windowVar.msSaveOrOpenBlob) {
       windowVar.msSaveOrOpenBlob(newBlob);
@@ -284,7 +305,7 @@ export class PublishApiComponent implements OnInit {
   }
 
   addParameter(request: Request): void {
-    let emptyParameter: Parameter = this.openApiDTOMappingService.getEmptyParameter(false, '');
+    const emptyParameter: Parameter = this.openApiDTOMappingService.getEmptyParameter(false, '');
     request.parameters.unshift(emptyParameter);
   }
 
@@ -302,7 +323,7 @@ export class PublishApiComponent implements OnInit {
   }
 
   addResponse(request: Request): void {
-    let emptyResponse: Response = this.openApiDTOMappingService.getEmptyResponse();
+    const emptyResponse: Response = this.openApiDTOMappingService.getEmptyResponse();
     request.responses.unshift(emptyResponse);
   }
 
@@ -320,7 +341,7 @@ export class PublishApiComponent implements OnInit {
   importJson(event: Event): void {
     const files: FileList = (event.target as HTMLInputElement).files;
     const jsonFile: File = files[0];
-    var reader = new FileReader();
+    const reader = new FileReader();
 
     reader.onload = () => {
       console.log(reader.result as string);
@@ -330,14 +351,14 @@ export class PublishApiComponent implements OnInit {
       this.openApi = this.openApiService.getFromString(reader.result as string);
       this.openApi.cleanServers(servers[0].url);
       this.openApi.info['x-catalog-id'] = catId;
-      
+
     };
 
     reader.readAsText(jsonFile);
   }
 
   goToLink() {
-    window.open("/swaggerapi");
+    window.open('/swaggerapi');
   }
 
   duplicatePath(path: Path) {
@@ -363,5 +384,19 @@ export class PublishApiComponent implements OnInit {
   openDatasetsSelectDialog() {
     this.datasets.openDatasetsSelectDialog(this.stepper);
   }
+
+  getKeywords() {
+    let keywordPaths: string[] = [];
+    if (this.paths !== null) {
+      for (const path of this.paths) {
+        if (path.dcatClass === 'dcat:keyword') {
+          keywordPaths.push(path.path);
+        }
+      }
+
+      const data = new KeywordRequest(this.isJsonPath, keywordPaths);
+    }
+  }
+
 }
 
diff --git a/src/app/semantic-enrichment/semantic-enrichment.component.html b/src/app/semantic-enrichment/semantic-enrichment.component.html
new file mode 100644
index 000000000..87756692f
--- /dev/null
+++ b/src/app/semantic-enrichment/semantic-enrichment.component.html
@@ -0,0 +1,40 @@
+<nb-layout>
+  <nb-layout-header fixed>
+    <img width="80" alt="Angular Logo" src="assets/images/logo.png"/>
+    <h3 style="width: 100%;text-align: center;"><strong></strong></h3>
+    <div style="float: right;">
+      <button (click)="login()" status="primary" nbButton>login</button>
+    </div>
+
+
+  </nb-layout-header>
+
+  <nb-layout-column>
+
+    <nb-card size="small">
+      <nb-card-body>
+        <nb-form-field>
+          <input
+            type="text"
+            placeholder="Enter Location"
+            [formControl]="myControl"
+            nbInput
+            [nbAutocomplete]="auto">
+          <nb-autocomplete #auto [handleDisplayFn]="viewHandle">
+            <nb-option
+              *ngFor="let option of filteredOptions | async"
+              [value]="option">
+              {{option.name}}
+            </nb-option>
+          </nb-autocomplete>
+        </nb-form-field>
+      </nb-card-body>
+    </nb-card>
+    <p *ngIf="myControl.value !== null">{{ myControl.value | json }}</p>
+  </nb-layout-column>
+
+
+  <nb-layout-footer>Contact us</nb-layout-footer>
+
+
+
diff --git a/src/app/semantic-enrichment/semantic-enrichment.component.scss b/src/app/semantic-enrichment/semantic-enrichment.component.scss
new file mode 100644
index 000000000..8b1378917
--- /dev/null
+++ b/src/app/semantic-enrichment/semantic-enrichment.component.scss
@@ -0,0 +1 @@
+
diff --git a/src/app/semantic-enrichment/semantic-enrichment.component.spec.ts b/src/app/semantic-enrichment/semantic-enrichment.component.spec.ts
new file mode 100644
index 000000000..f515fc3d7
--- /dev/null
+++ b/src/app/semantic-enrichment/semantic-enrichment.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { SemanticEnrichmentComponent } from './semantic-enrichment.component';
+
+describe('SemanticEnrichmentComponent', () => {
+  let component: SemanticEnrichmentComponent;
+  let fixture: ComponentFixture<SemanticEnrichmentComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ SemanticEnrichmentComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(SemanticEnrichmentComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/src/app/semantic-enrichment/semantic-enrichment.component.ts b/src/app/semantic-enrichment/semantic-enrichment.component.ts
new file mode 100644
index 000000000..b15b368f8
--- /dev/null
+++ b/src/app/semantic-enrichment/semantic-enrichment.component.ts
@@ -0,0 +1,57 @@
+
+import {Component, Input, OnInit} from '@angular/core';
+import {Path} from '../mapping/class/requestMapping';
+import {Observable} from 'rxjs';
+import {debounceTime, distinctUntilChanged, map, startWith, switchMap} from 'rxjs/operators';
+import {PostService} from './services/post.service';
+import {FormControl} from '@angular/forms';
+
+@Component({
+  selector: 'app-semantic-enrichment',
+  templateUrl: './semantic-enrichment.component.html',
+  styleUrls: ['./semantic-enrichment.component.scss']
+})
+export class SemanticEnrichmentComponent implements OnInit {
+
+  @Input()
+  paths: Path[];
+
+  myControl = new FormControl();
+  options = [];
+  filteredOptions: Observable<any>;
+
+  constructor(private service: PostService) {
+
+    this.filteredOptions = this.myControl.valueChanges.pipe(
+      startWith(''),
+      debounceTime(400),
+      distinctUntilChanged(),
+      switchMap(val => {
+        return this.filter(val || '');
+      })
+    );
+  }
+
+  ngOnInit(): void {
+    /*for ( let path of this.paths) {
+      if (path.property === 'dcat:keyword') {
+
+      }
+    }*/
+  }
+
+  filter(val: any): Observable<any> {
+    return this.service.getData()
+      .pipe(
+        map(response => response.filter((option: any) => {
+          return option.name.toLowerCase().includes(val.toLowerCase());
+        }))
+      );
+  }
+
+  viewHandle(value: any) {
+    return value.name;
+  }
+
+}
+
diff --git a/src/app/semantic-enrichment/services/post.service.spec.ts b/src/app/semantic-enrichment/services/post.service.spec.ts
new file mode 100644
index 000000000..913642b87
--- /dev/null
+++ b/src/app/semantic-enrichment/services/post.service.spec.ts
@@ -0,0 +1,16 @@
+import { TestBed } from '@angular/core/testing';
+
+import { PostService } from './post.service';
+
+describe('PostService', () => {
+  let service: PostService;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({});
+    service = TestBed.inject(PostService);
+  });
+
+  it('should be created', () => {
+    expect(service).toBeTruthy();
+  });
+});
diff --git a/src/app/semantic-enrichment/services/post.service.ts b/src/app/semantic-enrichment/services/post.service.ts
new file mode 100644
index 000000000..afb0b8d79
--- /dev/null
+++ b/src/app/semantic-enrichment/services/post.service.ts
@@ -0,0 +1,23 @@
+import { Injectable } from '@angular/core';
+import {HttpClient} from '@angular/common/http';
+import {of} from 'rxjs';
+import {tap} from 'rxjs/operators';
+
+@Injectable({
+  providedIn: 'root'
+})
+export class PostService {
+
+  constructor(private http: HttpClient) { }
+
+  opt = [];
+
+
+  getData() {
+    return this.opt.length ?
+      of(this.opt) :
+      this.http.get('https://jsonplaceholder.typicode.com/users').pipe(
+        tap((data: any) => this.opt = data)
+      );
+  }
+}
diff --git a/src/environments/environment.ts b/src/environments/environment.ts
index dce50e66a..133ced820 100644
--- a/src/environments/environment.ts
+++ b/src/environments/environment.ts
@@ -5,7 +5,7 @@
 export const environment = {
   production: false,
   smartharvesterUrl: 'http://localhost:8080',
-  fdpUrl: 'https://f2ds-dev.eosc-pillar.eu'
+  fdpUrl: 'http://10.6.10.97:8080'
 };
 
 /*
-- 
GitLab