diff --git a/ida-chatbot/src/app/app.component.ts b/ida-chatbot/src/app/app.component.ts
index 9d7f4333d..e05a6d492 100644
--- a/ida-chatbot/src/app/app.component.ts
+++ b/ida-chatbot/src/app/app.component.ts
@@ -11,6 +11,8 @@ import {TabElement} from './models/tab-element';
import {UniqueIdProviderService} from './service/misc/unique-id-provider.service';
import {TabType} from './enums/tab-type.enum';
import {IdaEventService} from './service/event/ida-event.service';
+import {MatDialog} from '@angular/material';
+import {DatasetUploadModalComponent} from './components/dataset-upload-modal/dataset-upload-modal.component';
@Component({
selector: 'app-root',
@@ -31,7 +33,7 @@ export class AppComponent {
@ViewChild(SidebarComponent)
private sbComp: SidebarComponent;
- constructor(private restservice: RestService, private uis: UniqueIdProviderService, private ies: IdaEventService) {
+ constructor(private restservice: RestService, private uis: UniqueIdProviderService, private ies: IdaEventService, public dialog: MatDialog) {
ies.dtTblEvnt.subscribe((reqTbl) => {
this.getDataTable(reqTbl);
});
@@ -65,6 +67,14 @@ export class AppComponent {
// Open new tab with DataTable
const newTab = new TabElement(this.uis.getUniqueId(), resp.payload.actvTbl, TabType.DTTBL, resp.payload.dataTable, true, true);
this.addNewTab(newTab, resp);
+ } else if (resp.actnCode === 6) {
+ this.dialog.open(DatasetUploadModalComponent, {
+ data: {
+ datasetName: resp.payload.datasetName
+ },
+ disableClose: true,
+ width: '350px'
+ });
} else if (resp.actnCode === 7) {
// Open new tab with DataTable
const newTab = new TabElement(this.uis.getUniqueId(), resp.payload.actvTbl, TabType.VENND, resp.payload.vennDiagramData, true, true);
diff --git a/ida-chatbot/src/app/app.module.ts b/ida-chatbot/src/app/app.module.ts
index 455cb2dd3..4f9b98710 100644
--- a/ida-chatbot/src/app/app.module.ts
+++ b/ida-chatbot/src/app/app.module.ts
@@ -60,6 +60,7 @@ import {DatatableDetailComponent} from './components/datatable-detail/datatable-
import { SsbViewComponent } from './components/ssb-view/ssb-view.component';
import { VennViewComponent } from './components/venn-view/venn-view.component';
import { DeckglHexViewComponent } from './components/deckgl-hex-view/deckgl-hex-view.component';
+import { DatasetUploadModalComponent } from './components/dataset-upload-modal/dataset-upload-modal.component';
@NgModule({
declarations: [
AppComponent,
@@ -78,7 +79,8 @@ import { DeckglHexViewComponent } from './components/deckgl-hex-view/deckgl-hex-
DatatableDetailComponent,
SsbViewComponent,
VennViewComponent,
- DeckglHexViewComponent
+ DeckglHexViewComponent,
+ DatasetUploadModalComponent
],
imports: [
BrowserModule,
@@ -119,13 +121,15 @@ import { DeckglHexViewComponent } from './components/deckgl-hex-view/deckgl-hex-
MatTabsModule,
MatToolbarModule,
MatTooltipModule,
- FlexLayoutModule
+ FlexLayoutModule,
+ MatSnackBarModule
],
providers: [{
provide: HTTP_INTERCEPTORS,
useClass: RestService ,
multi: true
}],
+ entryComponents: [DatasetUploadModalComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
diff --git a/ida-chatbot/src/app/components/dataset-upload-modal/dataset-upload-modal.component.css b/ida-chatbot/src/app/components/dataset-upload-modal/dataset-upload-modal.component.css
new file mode 100644
index 000000000..e1d12d8a8
--- /dev/null
+++ b/ida-chatbot/src/app/components/dataset-upload-modal/dataset-upload-modal.component.css
@@ -0,0 +1,3 @@
+.file-name:disabled {
+ color: #000;
+}
diff --git a/ida-chatbot/src/app/components/dataset-upload-modal/dataset-upload-modal.component.html b/ida-chatbot/src/app/components/dataset-upload-modal/dataset-upload-modal.component.html
new file mode 100644
index 000000000..a3be3b5b0
--- /dev/null
+++ b/ida-chatbot/src/app/components/dataset-upload-modal/dataset-upload-modal.component.html
@@ -0,0 +1,24 @@
+
Upload dataset
+
+
+
+
+
+
+
+
+
diff --git a/ida-chatbot/src/app/components/dataset-upload-modal/dataset-upload-modal.component.spec.ts b/ida-chatbot/src/app/components/dataset-upload-modal/dataset-upload-modal.component.spec.ts
new file mode 100644
index 000000000..75d3bc4e1
--- /dev/null
+++ b/ida-chatbot/src/app/components/dataset-upload-modal/dataset-upload-modal.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { DatasetUploadModalComponent } from './dataset-upload-modal.component';
+
+describe('DatasetUploadModalComponent', () => {
+ let component: DatasetUploadModalComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ DatasetUploadModalComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(DatasetUploadModalComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/ida-chatbot/src/app/components/dataset-upload-modal/dataset-upload-modal.component.ts b/ida-chatbot/src/app/components/dataset-upload-modal/dataset-upload-modal.component.ts
new file mode 100644
index 000000000..0f1fea90a
--- /dev/null
+++ b/ida-chatbot/src/app/components/dataset-upload-modal/dataset-upload-modal.component.ts
@@ -0,0 +1,55 @@
+import {Component, Inject, Input, OnInit} from '@angular/core';
+import {HttpClient} from '@angular/common/http';
+import {MAT_DIALOG_DATA, MatDialogRef, MatSnackBar} from '@angular/material';
+
+@Component({
+ selector: 'app-dialog-modal',
+ templateUrl: './dataset-upload-modal.component.html',
+ styleUrls: ['./dataset-upload-modal.component.css']
+})
+export class DatasetUploadModalComponent implements OnInit {
+
+ fileName = 'Select CSV or XML file...';
+ file;
+ fileSelected = false;
+ showProgress = false;
+
+ constructor(@Inject(MAT_DIALOG_DATA) public data,
+ private _http: HttpClient,
+ public dialogRef: MatDialogRef,
+ public snackBar: MatSnackBar) {}
+
+ ngOnInit() {
+ }
+
+ fileManager(event) {
+ if (event.target.files.length > 0) {
+ this.fileSelected = true;
+ this.file = event.target.files[0];
+ this.fileName = this.file.name;
+ }
+ }
+
+ uploadDataset() {
+ console.log(this.data.datasetName);
+ this.showProgress = true;
+ const formData = new FormData();
+ formData.append('file', this.file);
+ formData.append('fileName', this.data.datasetName);
+ this._http.post('http://localhost:8080/ida-ws/message/file', formData).subscribe(
+ (res) => {
+ this.dialogRef.close();
+ this.snackBar.open('Dataset uploaded successfully', 'Close', {
+ duration: 3000,
+ });
+ },
+ (err) => {
+ this.snackBar.open('Dataset upload failed! Please try again', 'Close', {
+ duration: 3000,
+ });
+ this.showProgress = false;
+ }
+ );
+ }
+
+}
diff --git a/ida-chatbot/src/styles.css b/ida-chatbot/src/styles.css
index 59573638b..75f5db184 100644
--- a/ida-chatbot/src/styles.css
+++ b/ida-chatbot/src/styles.css
@@ -7,7 +7,9 @@ html, body {
height: 100%;
margin: 0;
}
-
+.full-width {
+ width: 100%;
+}
.table-cls {
margin: 15px;
}
diff --git a/ida-ws/pom.xml b/ida-ws/pom.xml
index f5d4934d6..77f80b530 100644
--- a/ida-ws/pom.xml
+++ b/ida-ws/pom.xml
@@ -179,6 +179,17 @@
topicmodeling.commons
0.0.3-SNAPSHOT
+
+ org.apache.jena
+ apache-jena-libs
+ 3.9.0
+ pom
+
+
+ no.acando
+ xmltordf
+ 1.9.1
+
org.springframework.boot
@@ -186,7 +197,6 @@
2.1.0.RELEASE
test
-
ida-ws
diff --git a/ida-ws/src/main/java/upb/ida/constant/IDALiteral.java b/ida-ws/src/main/java/upb/ida/constant/IDALiteral.java
index 06914bd0a..5fc475b8d 100644
--- a/ida-ws/src/main/java/upb/ida/constant/IDALiteral.java
+++ b/ida-ws/src/main/java/upb/ida/constant/IDALiteral.java
@@ -7,12 +7,13 @@
public interface IDALiteral {
public static final String EXAMPLE = "this is an example constant string";
- //Action literals
+ //Action literals (User Interface Action)
public static final int UIA_LOADDS = 1;
public static final int UIA_FDG = 2;
public static final int UIA_BG = 3;
public static final int UIA_CLUSTER = 4;
public static final int UIA_DTTABLE = 5;
+ public static final int UIA_UPLOAD = 6;
public static final int UIA_VENNDIAGRAM = 7;
public static final int UIA_GSDIAGRAM = 8;
@@ -37,4 +38,6 @@ public interface IDALiteral {
//Metadata File name Pattern
public static final String DSMD_FILE_PATTERN = ".*_dsmd\\.[jJ][sS][oO][nN]$";
+ public static final String DS_PATH = System.getProperty("user.dir") + "/uploads/";
+
}
diff --git a/ida-ws/src/main/java/upb/ida/provider/LoadDsMetadata.java b/ida-ws/src/main/java/upb/ida/provider/LoadDsMetadata.java
index d47250178..7438059c2 100644
--- a/ida-ws/src/main/java/upb/ida/provider/LoadDsMetadata.java
+++ b/ida-ws/src/main/java/upb/ida/provider/LoadDsMetadata.java
@@ -1,8 +1,11 @@
package upb.ida.provider;
import java.io.IOException;
+import java.util.HashMap;
import java.util.Map;
+import org.apache.jena.rdf.model.Model;
+import org.apache.jena.util.FileManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -12,6 +15,9 @@
import upb.ida.bean.ResponseBean;
import upb.ida.constant.IDALiteral;
import upb.ida.util.FileUtil;
+import upb.ida.util.SessionUtil;
+
+import static upb.ida.constant.IDALiteral.DS_PATH;
/**
* LoadDataContent is a subroutine that loads the data
@@ -25,7 +31,8 @@ public class LoadDsMetadata implements Subroutine {
private FileUtil fileUtil;
@Autowired
private ResponseBean responseBean;
-
+ @Autowired
+ private SessionUtil sessionUtil;
/**
* Method to create response for loading the data set
*
@@ -41,6 +48,12 @@ public String call(com.rivescript.RiveScript rs, String[] args) {
if (fileUtil.datasetExists(message)) {
try {
Map dataMap = responseBean.getPayload();
+ Model model = FileManager.get().loadModel(DS_PATH + message + ".ttl");
+ Map dsMap = new HashMap<>();
+ if(!dsMap.containsKey(message)){
+ dsMap.put(message, model);
+ sessionUtil.getSessionMap().put("DSModel", dsMap);
+ }
dataMap.put("label", message);
dataMap.put("dsName", message);
dataMap.put("dsMd", fileUtil.getDatasetMetaData(message));
diff --git a/ida-ws/src/main/java/upb/ida/provider/RiveScriptBeanProvider.java b/ida-ws/src/main/java/upb/ida/provider/RiveScriptBeanProvider.java
index 920deea26..99892eb90 100644
--- a/ida-ws/src/main/java/upb/ida/provider/RiveScriptBeanProvider.java
+++ b/ida-ws/src/main/java/upb/ida/provider/RiveScriptBeanProvider.java
@@ -46,6 +46,10 @@ public class RiveScriptBeanProvider {
@Autowired
private LoadDsMetadata dsmdLoader;
@Autowired
+ private UploadDataset uploadDataset;
+ @Autowired
+ private ShowDataset showDataset;
+ @Autowired
private VennDiagramHandler VennDiagramHandler;
@Autowired
private GeoDiagramHandler GeoDiagramHandler;
@@ -77,6 +81,8 @@ public RiveScript initBotInstance() {
bot.setSubroutine("ClusterDataGetter", clusterDataGetter);
bot.setSubroutine("CheckParamCollected", checkParamCollected);
bot.setSubroutine("LoadDsMetadata", dsmdLoader);
+ bot.setSubroutine("UploadDataset", uploadDataset);
+ bot.setSubroutine("ShowDataset", showDataset);
bot.setSubroutine("VennDiagramHandler", VennDiagramHandler);
bot.setSubroutine("GeoDiagramHandler", GeoDiagramHandler);
return bot;
diff --git a/ida-ws/src/main/java/upb/ida/provider/ShowDataset.java b/ida-ws/src/main/java/upb/ida/provider/ShowDataset.java
new file mode 100644
index 000000000..176c2c31f
--- /dev/null
+++ b/ida-ws/src/main/java/upb/ida/provider/ShowDataset.java
@@ -0,0 +1,31 @@
+package upb.ida.provider;
+
+import com.rivescript.macro.Subroutine;
+import org.apache.commons.io.FilenameUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import upb.ida.bean.ResponseBean;
+
+import java.io.File;
+
+import static upb.ida.constant.IDALiteral.DS_PATH;
+
+
+@Component
+public class ShowDataset implements Subroutine {
+ @Autowired
+ private ResponseBean responseBean;
+
+ public String call(com.rivescript.RiveScript rs, String[] args) {
+ File directory = new File(DS_PATH);
+ String[] files = directory.list();
+ String temp = "Datasets: ";
+ for (String file: files) {
+ temp = temp + FilenameUtils.removeExtension(file) + ", ";
+ }
+
+ responseBean.setChatmsg(DS_PATH);
+ temp = temp.substring(0, temp.length() - 1);
+ return temp;
+ }
+}
diff --git a/ida-ws/src/main/java/upb/ida/provider/UploadDataset.java b/ida-ws/src/main/java/upb/ida/provider/UploadDataset.java
new file mode 100644
index 000000000..071a691f6
--- /dev/null
+++ b/ida-ws/src/main/java/upb/ida/provider/UploadDataset.java
@@ -0,0 +1,30 @@
+package upb.ida.provider;
+
+import com.rivescript.macro.Subroutine;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import upb.ida.bean.ResponseBean;
+import upb.ida.constant.IDALiteral;
+
+import java.io.File;
+import java.util.Map;
+
+@Component
+public class UploadDataset implements Subroutine {
+ @Autowired
+ private ResponseBean responseBean;
+
+ public String call(com.rivescript.RiveScript rs, String[] args) {
+ String message = args[0].toLowerCase().trim();
+ Map dataMap = responseBean.getPayload();
+ dataMap.put("datasetName", message);
+ String resp = IDALiteral.RESP_FAIL_ROUTINE;
+ File file = new File(System.getProperty("user.dir") + "/upload-ds/" + message + ".ttl");
+ if (!file.exists()) {
+ responseBean.setActnCode(IDALiteral.UIA_UPLOAD);
+ responseBean.setPayload(dataMap);
+ resp = IDALiteral.RESP_PASS_ROUTINE;
+ }
+ return resp;
+ }
+}
diff --git a/ida-ws/src/main/java/upb/ida/rest/MessageRestController.java b/ida-ws/src/main/java/upb/ida/rest/MessageRestController.java
index 6e89596e4..e0f648e06 100644
--- a/ida-ws/src/main/java/upb/ida/rest/MessageRestController.java
+++ b/ida-ws/src/main/java/upb/ida/rest/MessageRestController.java
@@ -1,17 +1,24 @@
package upb.ida.rest;
+import java.io.*;
import java.util.HashMap;
import java.util.Map;
+import org.apache.jena.query.*;
+import org.apache.jena.util.FileManager;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.CrossOrigin;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
import upb.ida.bean.ResponseBean;
+import org.apache.jena.rdf.model.Model;
import upb.ida.service.DataService;
import upb.ida.service.RiveScriptService;
+import upb.ida.util.SessionUtil;
+import upb.ida.util.UploadManager;
+import upb.ida.util.FileConversionUtil;
+
+import static upb.ida.constant.IDALiteral.DS_PATH;
/**
* Exposes RESTful RPCs for the IDA Chatbot
@@ -29,6 +36,11 @@ public class MessageRestController {
private RiveScriptService rsService;
@Autowired
private DataService dataService;
+ @Autowired
+ private SessionUtil sessionUtil;
+
+ private int id = 0;
+
@RequestMapping("/sayhello")
public String greeting(@RequestParam(value = "name", defaultValue = "World") String name) {
return "Hello " + name + "!";
@@ -53,7 +65,7 @@ public ResponseBean sendmessage(@RequestParam(value = "msg") String msg,
dataMap.put("actvDs", actvDs);
response.setPayload(dataMap);
String reply = rsService.getRSResponse(msg);
-
+
response.setChatmsg(reply);
return response;
}
@@ -71,4 +83,44 @@ public ResponseBean getDataTable(@RequestParam(value = "actvScrId") String actvS
return response;
}
-}
\ No newline at end of file
+ @PostMapping("/file")
+ public ResponseBean convert(@RequestParam(value="file") MultipartFile file, @RequestParam(value="fileName") String fileName) throws IOException, Exception{
+// TODO: ID unique implementation required
+
+ if(file.getContentType().equals("text/xml") && UploadManager.getFileExtension(file.getOriginalFilename()).equals("xml")){
+ byte[] bytes = file.getBytes();
+ UploadManager.saveFile(fileName.toLowerCase(), FileConversionUtil.xmlToRDF(bytes));
+ }
+ else if(file.getContentType().equals("text/csv") && UploadManager.getFileExtension(file.getOriginalFilename()).equals("csv")){
+ byte[] bytes = file.getBytes();
+ UploadManager.saveFile(fileName.toLowerCase(), FileConversionUtil.csvToRDF(bytes));
+ }
+// Map fileMap = new HashMap<>();
+ Map idMap = new HashMap<>();
+ idMap.put(id, DS_PATH + fileName + ".ttl");
+// fileMap.put("FileMap", idMap);
+ id++;
+// response.setPayload(fileMap);
+ sessionUtil.getSessionMap().put("FileMap", idMap);
+ response.setChatmsg("Please download the file at: " + fileName + "");
+ return response;
+ }
+
+ @GetMapping(value = "/sparql")
+ public String getbyArtist(@RequestParam("query") String queryString, @RequestParam("datasetName") String datasetName) {
+ // TODO: Error handling e.g. if dataset name is invalid
+
+ Model model = FileManager.get().loadModel(DS_PATH + datasetName + ".ttl");
+ Query query = QueryFactory.create(queryString);
+ QueryExecution qexec = QueryExecutionFactory.create(query, model);
+
+ ResultSet results = qexec.execSelect();
+
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ ResultSetFormatter.outputAsJSON(outputStream, results);
+ String json = new String(outputStream.toByteArray());
+
+ return json;
+ }
+
+}
diff --git a/ida-ws/src/main/java/upb/ida/util/FileConversionUtil.java b/ida-ws/src/main/java/upb/ida/util/FileConversionUtil.java
new file mode 100644
index 000000000..b4c7008d4
--- /dev/null
+++ b/ida-ws/src/main/java/upb/ida/util/FileConversionUtil.java
@@ -0,0 +1,37 @@
+package upb.ida.util;
+
+import no.acando.xmltordf.Builder;
+import org.apache.jena.query.Dataset;
+import org.apache.jena.rdf.model.Model;
+import org.apache.jena.rdf.model.ModelFactory;
+import org.xml.sax.SAXException;
+
+import javax.xml.parsers.ParserConfigurationException;
+import java.io.*;
+
+public class FileConversionUtil {
+ public static byte[] xmlToRDF(byte[] bytes) throws IOException, SAXException, ParserConfigurationException {
+ InputStream inputStream = new ByteArrayInputStream(bytes);
+
+ BufferedInputStream in = new BufferedInputStream(inputStream);
+ Dataset dataset = Builder.getAdvancedBuilderJena().build().convertToDataset(in);
+ ByteArrayOutputStream stream = new ByteArrayOutputStream();
+ // converting it into turtle format
+ dataset.getDefaultModel().write(stream, "ttl");
+
+ return stream.toByteArray();
+ }
+
+ public static byte[] csvToRDF(byte[] bytes) {
+ InputStream inputStream = new ByteArrayInputStream(bytes);
+
+ Model m = ModelFactory.createDefaultModel();
+ // (TODO) http://example.com must not be fixed
+ m.read(inputStream, "http://example.com", "csv");
+ m.setNsPrefix("test", "http://example.com#");
+ ByteArrayOutputStream stream = new ByteArrayOutputStream();
+ // Converting into turtle format
+ m.write(stream, "ttl");
+ return stream.toByteArray();
+ }
+}
diff --git a/ida-ws/src/main/java/upb/ida/util/FileUtil.java b/ida-ws/src/main/java/upb/ida/util/FileUtil.java
index e9aa69eb5..e33eaeff7 100644
--- a/ida-ws/src/main/java/upb/ida/util/FileUtil.java
+++ b/ida-ws/src/main/java/upb/ida/util/FileUtil.java
@@ -23,6 +23,8 @@
import upb.ida.constant.IDALiteral;
+import static upb.ida.constant.IDALiteral.DS_PATH;
+
/**
* Class to expose util methods for File based operations in IDA
*
@@ -166,6 +168,11 @@ public boolean datasetExists(String keyword) {
return dsPathMap.get(keyword.toLowerCase()) != null;
}
+ public boolean dsExists(String filename){
+ File file = new File(DS_PATH + filename.toLowerCase() + ".ttl");
+ return file.exists();
+ }
+
/**
* Method to fetch the filePath of a given datable
*
diff --git a/ida-ws/src/main/java/upb/ida/util/UploadManager.java b/ida-ws/src/main/java/upb/ida/util/UploadManager.java
new file mode 100644
index 000000000..6c166b978
--- /dev/null
+++ b/ida-ws/src/main/java/upb/ida/util/UploadManager.java
@@ -0,0 +1,30 @@
+package upb.ida.util;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class UploadManager {
+ public static boolean saveFile (String fileName, byte[] contentInBytes) {
+ boolean success = false;
+ try {
+ if (! Paths.get("/uploads/").toFile().isDirectory()) {
+ // If uploads folder did not exists then create it
+ new File(System.getProperty("user.dir") + "/uploads").mkdir();
+ }
+ Path path = Paths.get(System.getProperty("user.dir") + "/uploads/", fileName + ".ttl");
+ Files.write(path, contentInBytes);
+ success = true;
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return success;
+ }
+
+ public static String getFileExtension (String fileName) {
+ int dotIndex = fileName.lastIndexOf(".");
+ return dotIndex != -1 ? fileName.substring(dotIndex+1) : "";
+ }
+}
diff --git a/ida-ws/src/main/resources/rivescript/ida-fdg.rive b/ida-ws/src/main/resources/rivescript/ida-fdg.rive
index ed9e9d32f..277d6c7fc 100644
--- a/ida-ws/src/main/resources/rivescript/ida-fdg.rive
+++ b/ida-ws/src/main/resources/rivescript/ida-fdg.rive
@@ -36,7 +36,7 @@
+ display force graph for this dataset
@ show me fdg
-+ display froce graph for this file
++ display force graph for this file
@ show me fdg
+ i would like a force directed graph visualization for the current table
diff --git a/ida-ws/src/main/resources/rivescript/ida-show-ds.rive b/ida-ws/src/main/resources/rivescript/ida-show-ds.rive
new file mode 100644
index 000000000..9b8fad82c
--- /dev/null
+++ b/ida-ws/src/main/resources/rivescript/ida-show-ds.rive
@@ -0,0 +1,8 @@
+! version = 2.0
+
+//User queries for datasets show
++ show all datasets
+- ShowDataset
+
++ show me all the datasets
+- ShowDataset
\ No newline at end of file
diff --git a/ida-ws/src/main/resources/rivescript/ida-upload-ds.rive b/ida-ws/src/main/resources/rivescript/ida-upload-ds.rive
new file mode 100644
index 000000000..99ca55733
--- /dev/null
+++ b/ida-ws/src/main/resources/rivescript/ida-upload-ds.rive
@@ -0,0 +1,36 @@
+! version = 2.0
+
+//User queries for dataset upload
+
+// first sentence
++ i would like you to upload a dataset
+- Sure, what would you like to call your dataset?
+
++ i want to upload a dataset
+- Sure, what would you like to call your dataset?
+
++ i have to upload a dataset
+- Sure, and what would you like to name it?
+
++ i would like for you to upload a dataset
+- Sure, what would you like to call your dataset?
+
+// dataset name
+
++ call dataset *
+* UploadDataset == pass => You may now proceed to upload the dataset.
+- Dataset already exists
+
++ i would like you to call it *
+@ call dataset
+
++ call dataset *
+@ call dataset
+
+@ call dataset
+
++ call dataset *
+@ load dataset
+
++ name it *
+@ @ call dataset
diff --git a/ida-ws/upload-ds/sampleresult.ttl b/ida-ws/upload-ds/sampleresult.ttl
new file mode 100644
index 000000000..e5544d93a
--- /dev/null
+++ b/ida-ws/upload-ds/sampleresult.ttl
@@ -0,0 +1,21106 @@
+@prefix test: .
+
+[ test:City "Antofagasta" ;
+ test:Country "Chile" ;
+
+ 3453
+] .
+
+[ test:City "Rivne" ;
+ test:Country "Ukraine" ;
+
+ 434
+] .
+
+[ test:City "Wadhwan" ;
+ test:Country "India" ;
+
+ 989
+] .
+
+[ test:City "Tacna" ;
+ test:Country "Peru" ;
+
+ 1810
+] .
+
+[ test:City "Gera" ;
+ test:Country "Germany" ;
+
+ 2365
+] .
+
+[ test:City "Huixian" ;
+ test:Country "China" ;
+
+ 3025
+] .
+
+[ test:City "Odense" ;
+ test:Country "Denmark" ;
+
+ 9
+] .
+
+[ test:City "São Caetano do Sul" ;
+ test:Country "Brazil" ;
+
+ 597
+] .
+
+[ test:City "Clearwater" ;
+ test:Country "United States" ;
+
+ 1224
+] .
+
+[ test:City "Tuticorin" ;
+ test:Country "India" ;
+
+ 2000
+] .
+
+[ test:City "Bat Yam" ;
+ test:Country "Israel" ;
+
+ 2600
+] .
+
+[ test:City "Naucalpan" ;
+ test:Country "Mexico" ;
+
+ 895
+] .
+
+[ test:City "Ust-Ilimsk" ;
+ test:Country "Russia" ;
+
+ 2235
+] .
+
+[ test:City "Hapur" ;
+ test:Country "India" ;
+
+ 2931
+] .
+
+[ test:City "Arusha" ;
+ test:Country "Tanzania" ;
+
+ 3486
+] .
+
+[ test:City "Saarbrücken" ;
+ test:Country "Germany" ;
+
+ 467
+] .
+
+[ test:City "Windhoek" ;
+ test:Country "Namibia" ;
+
+ 1022
+] .
+
+[ test:City "Tampa, Florida" ;
+ test:Country "United States" ;
+
+ 1843
+] .
+
+[ test:City "Changchun" ;
+ test:Country "China" ;
+
+ 1130
+] .
+
+[ test:City "Gorzów Wielkopolski" ;
+ test:Country "Poland" ;
+
+ 2398
+] .
+
+[ test:City "León" ;
+ test:Country "Nicaragua" ;
+
+ 3094
+] .
+
+[ test:City "Lansing" ;
+ test:Country "United States" ;
+
+ 3058
+] .
+
+[ test:City "Orange" ;
+ test:Country "United States" ;
+
+ 42
+] .
+
+[ test:City "Cusco" ;
+ test:Country "Peru" ;
+
+ 1293
+] .
+
+[ test:City "Coquimbo" ;
+ test:Country "Chile" ;
+
+ 1257
+] .
+
+[ test:City "Belém" ;
+ test:Country "Brazil" ;
+
+ 2633
+] .
+
+[ test:City "Abohar" ;
+ test:Country "India" ;
+
+ 3329
+] .
+
+[ test:City "Raipur" ;
+ test:Country "India" ;
+
+ 373
+] .
+
+[ test:City "Niamey" ;
+ test:Country "Niger" ;
+
+ 928
+] .
+
+[ test:City "Konya" ;
+ test:Country "Turkey" ;
+
+ 1713
+] .
+
+[ test:City "Jeonju" ;
+ test:Country "South Korea" ;
+
+ 2268
+] .
+
+[ test:City "Hialeah" ;
+ test:Country "United States" ;
+
+ 2964
+] .
+
+[ test:City "Salihorsk" ;
+ test:Country "Belarus" ;
+
+ 500
+] .
+
+[ test:City "Tehran" ;
+ test:Country "Iran" ;
+
+ 1876
+] .
+
+[ test:City "Chía" ;
+ test:Country "Colombia" ;
+
+ 1163
+] .
+
+[ test:City "Esenler" ;
+ test:Country "Turkey" ;
+
+ 2503
+] .
+
+[ test:City "Ourense" ;
+ test:Country "Spain" ;
+
+ 75
+] .
+
+[ test:City "Springfield, Massachusetts" ;
+ test:Country "United States" ;
+
+ 771
+] .
+
+[ test:City "Venice" ;
+ test:Country "Italy" ;
+
+ 1326
+] .
+
+[ test:City "Fu'an" ;
+ test:Country "China" ;
+
+ 2174
+] .
+
+[ test:City "Ajmer" ;
+ test:Country "India" ;
+
+ 3362
+] .
+
+[ test:City "Remscheid" ;
+ test:Country "Germany" ;
+
+ 406
+] .
+
+[ test:City "Kuala Lumpur" ;
+ test:Country "Malaysia" ;
+
+ 1746
+] .
+
+[ test:City "Jinhua" ;
+ test:Country "China" ;
+
+ 2301
+] .
+
+[ test:City "Greensboro" ;
+ test:Country "United States" ;
+
+ 2409
+] .
+
+[ test:City "Hospitalet de Llobregat" ;
+ test:Country "Spain" ;
+
+ 2997
+] .
+
+[ test:City "Seoul" ;
+ test:Country "South Korea" ;
+
+ 641
+] .
+
+[ test:City "Chonburi" ;
+ test:Country "Thailand" ;
+
+ 1196
+] .
+
+[ test:City "Barakaldo" ;
+ test:Country "Spain" ;
+
+ 2572
+] .
+
+[ test:City "Baicheng" ;
+ test:Country "China" ;
+
+ 2536
+] .
+
+[ test:City "Sukabumi" ;
+ test:Country "Indonesia" ;
+
+ 804
+] .
+
+[ test:City "Khenchela" ;
+ test:Country "Algeria" ;
+
+ 1652
+] .
+
+[ test:City "Vladivostok" ;
+ test:Country "Russia" ;
+
+ 1359
+] .
+
+[ test:City "Perugia" ;
+ test:Country "Italy" ;
+
+ 1431
+] .
+
+[ test:City "Uji" ;
+ test:Country "Japan" ;
+
+ 2207
+] .
+
+[ test:City "Allahabad" ;
+ test:Country "India" ;
+
+ 3395
+] .
+
+[ test:City "Muntinlupa City" ;
+ test:Country "Philippines" ;
+
+ 343
+] .
+
+[ test:City "Xiangfan" ;
+ test:Country "China" ;
+
+ 1779
+] .
+
+[ test:City "Gumi" ;
+ test:Country "South Korea" ;
+
+ 2442
+] .
+
+[ test:City "Huntington Beach" ;
+ test:Country "United States" ;
+
+ 3030
+] .
+
+[ test:City "Ogbomosho" ;
+ test:Country "Nigeria" ;
+
+ 14
+] .
+
+[ test:City "Sharjah" ;
+ test:Country "United Arab Emirates" ;
+
+ 674
+] .
+
+[ test:City "Zhumadian" ;
+ test:Country "China" ;
+
+ 2050
+] .
+
+[ test:City "Coatzacoalcos" ;
+ test:Country "Mexico" ;
+
+ 1229
+] .
+
+[ test:City "Bath" ;
+ test:Country "United Kingdom" ;
+
+ 2605
+] .
+
+[ test:City "Diwaniyah" ;
+ test:Country "Iraq" ;
+
+ 3265
+] .
+
+[ test:City "Syktyvkar" ;
+ test:Country "Russia" ;
+
+ 837
+] .
+
+[ test:City "Kisumu" ;
+ test:Country "Kenya" ;
+
+ 1685
+] .
+
+[ test:City "Piraeus" ;
+ test:Country "Greece" ;
+
+ 1464
+] .
+
+[ test:City "Jabalpur" ;
+ test:Country "India" ;
+
+ 2240
+] .
+
+[ test:City "Independence" ;
+ test:Country "United States" ;
+
+ 2840
+] .
+
+[ test:City "Changwon" ;
+ test:Country "South Korea" ;
+
+ 1135
+] .
+
+[ test:City "El Monte" ;
+ test:Country "United States" ;
+
+ 2475
+] .
+
+[ test:City "Orenburg" ;
+ test:Country "Russia" ;
+
+ 47
+] .
+
+[ test:City "Ludhiana" ;
+ test:Country "India" ;
+
+ 3171
+] .
+
+[ test:City "Macapá" ;
+ test:Country "Brazil" ;
+
+ 119
+] .
+
+[ test:City "Shuozhou" ;
+ test:Country "China" ;
+
+ 707
+] .
+
+[ test:City "Yangzhou" ;
+ test:Country "China" ;
+
+ 2083
+] .
+
+[ test:City "Córdoba" ;
+ test:Country "Spain" ;
+
+ 1262
+] .
+
+[ test:City "Belgrade" ;
+ test:Country "Serbia" ;
+
+ 2638
+] .
+
+[ test:City "Accra" ;
+ test:Country "Ghana" ;
+
+ 3334
+] .
+
+[ test:City "Dunhua" ;
+ test:Country "China" ;
+
+ 3298
+] .
+
+[ test:City "Mirpur Khas" ;
+ test:Country "Pakistan" ;
+
+ 282
+] .
+
+[ test:City "Korolyov" ;
+ test:Country "Russia" ;
+
+ 1718
+] .
+
+[ test:City "Port Said" ;
+ test:Country "Egypt" ;
+
+ 1497
+] .
+
+[ test:City "Itami" ;
+ test:Country "Japan" ;
+
+ 2873
+] .
+
+[ test:City "Saraburi" ;
+ test:Country "Thailand" ;
+
+ 613
+] .
+
+[ test:City "Cartagena" ;
+ test:Country "Spain" ;
+
+ 1105
+] .
+
+[ test:City "Chicago" ;
+ test:Country "United States" ;
+
+ 1168
+] .
+
+[ test:City "Tonk" ;
+ test:Country "India" ;
+
+ 1953
+] .
+
+[ test:City "Essen" ;
+ test:Country "Germany" ;
+
+ 2508
+] .
+
+[ test:City "Oyama" ;
+ test:Country "Japan" ;
+
+ 80
+] .
+
+[ test:City "Damascus" ;
+ test:Country "Syria" ;
+
+ 3204
+] .
+
+[ test:City "Malasiqui, Pangasinan" ;
+ test:Country "Philippines" ;
+
+ 152
+] .
+
+[ test:City "Sloviansk" ;
+ test:Country "Ukraine" ;
+
+ 740
+] .
+
+[ test:City "Yonago" ;
+ test:Country "Japan" ;
+
+ 2116
+] .
+
+[ test:City "Paramaribo" ;
+ test:Country "Suriname" ;
+
+ 1403
+] .
+
+[ test:City "Boulder" ;
+ test:Country "United States" ;
+
+ 2743
+] .
+
+[ test:City "Montreal" ;
+ test:Country "Canada" ;
+
+ 315
+] .
+
+[ test:City "Pueblo, Colorado" ;
+ test:Country "United States" ;
+
+ 1530
+] .
+
+[ test:City "Guadalajara" ;
+ test:Country "Mexico" ;
+
+ 2414
+] .
+
+[ test:City "Haiphong" ;
+ test:Country "Vietnam" ;
+
+ 2906
+] .
+
+[ test:City "Serra" ;
+ test:Country "Brazil" ;
+
+ 646
+] .
+
+[ test:City "Tulsa, Oklahoma" ;
+ test:Country "United States" ;
+
+ 1986
+] .
+
+[ test:City "Bakersfield" ;
+ test:Country "United States" ;
+
+ 2541
+] .
+
+[ test:City "Denver" ;
+ test:Country "United States" ;
+
+ 3237
+] .
+
+[ test:City "Maracanau" ;
+ test:Country "Brazil" ;
+
+ 185
+] .
+
+[ test:City "Kaiyuan" ;
+ test:Country "China" ;
+
+ 1561
+] .
+
+[ test:City "Nantong" ;
+ test:Country "China" ;
+
+ 881
+] .
+
+[ test:City "Petaling Jaya" ;
+ test:Country "Malaysia" ;
+
+ 1436
+] .
+
+[ test:City "Bucheon" ;
+ test:Country "South Korea" ;
+
+ 2776
+] .
+
+[ test:City "Murom" ;
+ test:Country "Russia" ;
+
+ 348
+] .
+
+[ test:City "Wuyishan" ;
+ test:Country "China" ;
+
+ 1044
+] .
+
+[ test:City "Termez" ;
+ test:Country "Uzbekistan" ;
+
+ 1892
+] .
+
+[ test:City "Gurgaon" ;
+ test:Country "India" ;
+
+ 2447
+] .
+
+[ test:City "Santarém, Brazil" ;
+ test:Country "Brazil" ;
+
+ 583
+] .
+
+[ test:City "Zaozhuang" ;
+ test:Country "China" ;
+
+ 2019
+] .
+
+[ test:City "Białystok" ;
+ test:Country "Poland" ;
+
+ 2682
+] .
+
+[ test:City "Dnipropetrovsk" ;
+ test:Country "Ukraine" ;
+
+ 3270
+] .
+
+[ test:City "Matsuyama" ;
+ test:Country "Japan" ;
+
+ 218
+] .
+
+[ test:City "Kaolack" ;
+ test:Country "Senegal" ;
+
+ 1594
+] .
+
+[ test:City "Navi Mumbai" ;
+ test:Country "India" ;
+
+ 914
+] .
+
+[ test:City "Plano, Texas" ;
+ test:Country "United States" ;
+
+ 1469
+] .
+
+[ test:City "Ingolstadt" ;
+ test:Country "Germany" ;
+
+ 2845
+] .
+
+[ test:City "Ibagué" ;
+ test:Country "Colombia" ;
+
+ 2809
+] .
+
+[ test:City "Atsugi" ;
+ test:Country "Japan" ;
+
+ 3505
+] .
+
+[ test:City "Cambridge" ;
+ test:Country "United States" ;
+
+ 1077
+] .
+
+[ test:City "Titagarh" ;
+ test:Country "India" ;
+
+ 1925
+] .
+
+[ test:City "Elbląg" ;
+ test:Country "Poland" ;
+
+ 2480
+] .
+
+[ test:City "Leganés" ;
+ test:Country "Spain" ;
+
+ 3080
+] .
+
+[ test:City "Macheng" ;
+ test:Country "China" ;
+
+ 124
+] .
+
+[ test:City "Bobo-Dioulasso" ;
+ test:Country "Burkina Faso" ;
+
+ 2715
+] .
+
+[ test:City "Miskolc" ;
+ test:Country "Hungary" ;
+
+ 287
+] .
+
+[ test:City "Mérida" ;
+ test:Country "Venezuela" ;
+
+ 251
+] .
+
+[ test:City "Münster" ;
+ test:Country "Germany" ;
+
+ 359
+] .
+
+[ test:City "Kawasaki" ;
+ test:Country "Japan" ;
+
+ 1627
+] .
+
+[ test:City "Nizhny Novgorod" ;
+ test:Country "Russia" ;
+
+ 947
+] .
+
+[ test:City "Jos" ;
+ test:Country "Nigeria" ;
+
+ 2323
+] .
+
+[ test:City "Porto Novo" ;
+ test:Country "Benin" ;
+
+ 1502
+] .
+
+[ test:City "Itu" ;
+ test:Country "Brazil" ;
+
+ 2878
+] .
+
+[ test:City "San Diego, California" ;
+ test:Country "United States" ;
+
+ 522
+] .
+
+[ test:City "Casablanca" ;
+ test:Country "Morocco" ;
+
+ 1110
+] .
+
+[ test:City "Torreón" ;
+ test:Country "Mexico" ;
+
+ 1958
+] .
+
+[ test:City "Lilongwe" ;
+ test:Country "Malawi" ;
+
+ 3113
+] .
+
+[ test:City "Malita, Davao del Sur" ;
+ test:Country "Philippines" ;
+
+ 157
+] .
+
+[ test:City "Vilnius" ;
+ test:Country "Lithuania" ;
+
+ 1345
+] .
+
+[ test:City "Pardubice" ;
+ test:Country "Czech Republic" ;
+
+ 1408
+] .
+
+[ test:City "Fuxin" ;
+ test:Country "China" ;
+
+ 2193
+] .
+
+[ test:City "Bradford" ;
+ test:Country "United Kingdom" ;
+
+ 2748
+] .
+
+[ test:City "Moratuwa" ;
+ test:Country "Sri Lanka" ;
+
+ 320
+] .
+
+[ test:City "Annaba" ;
+ test:Country "Algeria" ;
+
+ 3444
+] .
+
+[ test:City "Ratlam" ;
+ test:Country "India" ;
+
+ 392
+] .
+
+[ test:City "Noyabrsk" ;
+ test:Country "Russia" ;
+
+ 980
+] .
+
+[ test:City "Geelong" ;
+ test:Country "Australia" ;
+
+ 2356
+] .
+
+[ test:City "Puli Khumri" ;
+ test:Country "Afghanistan" ;
+
+ 1535
+] .
+
+[ test:City "Halifax" ;
+ test:Country "Canada" ;
+
+ 2911
+] .
+
+[ test:City "Ho Chi Minh City" ;
+ test:Country "Vietnam" ;
+
+ 2983
+] .
+
+[ test:City "Sanandaj" ;
+ test:Country "Iran" ;
+
+ 555
+] .
+
+[ test:City "London" ;
+ test:Country "Canada" ;
+
+ 3146
+] .
+
+[ test:City "Mardan" ;
+ test:Country "Pakistan" ;
+
+ 190
+] .
+
+[ test:City "Kalisz" ;
+ test:Country "Poland" ;
+
+ 1566
+] .
+
+[ test:City "Nara" ;
+ test:Country "Japan" ;
+
+ 886
+] .
+
+[ test:City "Urdaneta" ;
+ test:Country "Philippines" ;
+
+ 2226
+] .
+
+[ test:City "Buffalo" ;
+ test:Country "United States" ;
+
+ 2781
+] .
+
+[ test:City "Argenteuil" ;
+ test:Country "France" ;
+
+ 3477
+] .
+
+[ test:City "Rio Branco" ;
+ test:Country "Brazil" ;
+
+ 425
+] .
+
+[ test:City "West Covina" ;
+ test:Country "United States" ;
+
+ 1013
+] .
+
+[ test:City "Xuancheng" ;
+ test:Country "China" ;
+
+ 1801
+] .
+
+[ test:City "Caxias" ;
+ test:Country "Brazil" ;
+
+ 1121
+] .
+
+[ test:City "Gold Coast" ;
+ test:Country "Australia" ;
+
+ 2389
+] .
+
+[ test:City "Huánuco" ;
+ test:Country "Peru" ;
+
+ 3016
+] .
+
+[ test:City "Ōmuta" ;
+ test:Country "Japan" ;
+
+ 33
+] .
+
+[ test:City "Santiago del Estero" ;
+ test:Country "Argentina" ;
+
+ 588
+] .
+
+[ test:City "Cúcuta" ;
+ test:Country "Colombia" ;
+
+ 1284
+] .
+
+[ test:City "Bijapur" ;
+ test:Country "India" ;
+
+ 2687
+] .
+
+[ test:City "Mayagüez" ;
+ test:Country "Puerto Rico" ;
+
+ 223
+] .
+
+[ test:City "Surat" ;
+ test:Country "India" ;
+
+ 823
+] .
+
+[ test:City "Karaman" ;
+ test:Country "Turkey" ;
+
+ 1599
+] .
+
+[ test:City "Kimberley" ;
+ test:Country "South Africa" ;
+
+ 1671
+] .
+
+[ test:City "Jaraguá do Sul" ;
+ test:Country "Brazil" ;
+
+ 2259
+] .
+
+[ test:City "Ichalakaranji" ;
+ test:Country "India" ;
+
+ 2814
+] .
+
+[ test:City "Hanam" ;
+ test:Country "South Korea" ;
+
+ 2922
+] .
+
+[ test:City "Augusta" ;
+ test:Country "United States" ;
+
+ 3510
+] .
+
+[ test:City "Ruichang" ;
+ test:Country "China" ;
+
+ 458
+] .
+
+[ test:City "Talcahuano" ;
+ test:Country "Chile" ;
+
+ 1834
+] .
+
+[ test:City "Chennai" ;
+ test:Country "India" ;
+
+ 1154
+] .
+
+[ test:City "Leipzig" ;
+ test:Country "Germany" ;
+
+ 3085
+] .
+
+[ test:City "Lahore" ;
+ test:Country "Pakistan" ;
+
+ 3049
+] .
+
+[ test:City "Ostrava" ;
+ test:Country "Czech Republic" ;
+
+ 66
+] .
+
+[ test:City "Varginha" ;
+ test:Country "Brazil" ;
+
+ 1317
+] .
+
+[ test:City "Franca" ;
+ test:Country "Brazil" ;
+
+ 2165
+] .
+
+[ test:City "Bogra" ;
+ test:Country "Bangladesh" ;
+
+ 2720
+] .
+
+[ test:City "Messad" ;
+ test:Country "Algeria" ;
+
+ 256
+] .
+
+[ test:City "Mytho" ;
+ test:Country "Vietnam" ;
+
+ 364
+] .
+
+[ test:City "Naihati" ;
+ test:Country "India" ;
+
+ 856
+] .
+
+[ test:City "Keelung" ;
+ test:Country "Taiwan" ;
+
+ 1632
+] .
+
+[ test:City "Kolar" ;
+ test:Country "India" ;
+
+ 1704
+] .
+
+[ test:City "Jijel" ;
+ test:Country "Algeria" ;
+
+ 2292
+] .
+
+[ test:City "Hengyang" ;
+ test:Country "China" ;
+
+ 2955
+] .
+
+[ test:City "San José" ;
+ test:Country "Costa Rica" ;
+
+ 527
+] .
+
+[ test:City "Sakata" ;
+ test:Country "Japan" ;
+
+ 491
+] .
+
+[ test:City "Tashkent" ;
+ test:Country "Uzbekistan" ;
+
+ 1867
+] .
+
+[ test:City "Chitradurga" ;
+ test:Country "India" ;
+
+ 1187
+] .
+
+[ test:City "Bani Suwayf" ;
+ test:Country "Egypt" ;
+
+ 2563
+] .
+
+[ test:City "Limoges" ;
+ test:Country "France" ;
+
+ 3118
+] .
+
+[ test:City "Visakhapatnam" ;
+ test:Country "India" ;
+
+ 1350
+] .
+
+[ test:City "Ube" ;
+ test:Country "Japan" ;
+
+ 2198
+] .
+
+[ test:City "Ahmednagar" ;
+ test:Country "India" ;
+
+ 3353
+] .
+
+[ test:City "Reading" ;
+ test:Country "United Kingdom" ;
+
+ 397
+] .
+
+[ test:City "Krasnodar" ;
+ test:Country "Russia" ;
+
+ 1737
+] .
+
+[ test:City "Guelma" ;
+ test:Country "Algeria" ;
+
+ 2433
+] .
+
+[ test:City "Homs" ;
+ test:Country "Syria" ;
+
+ 2988
+] .
+
+[ test:City "Obihiro" ;
+ test:Country "Japan" ;
+
+ 5
+] .
+
+[ test:City "Şanlıurfa" ;
+ test:Country "Turkey" ;
+
+ 560
+] .
+
+[ test:City "Seam Reab" ;
+ test:Country "Cambodia" ;
+
+ 632
+] .
+
+[ test:City "Ciudad Obregón" ;
+ test:Country "Mexico" ;
+
+ 1220
+] .
+
+[ test:City "Barysaw" ;
+ test:Country "Belarus" ;
+
+ 2596
+] .
+
+[ test:City "Longueuil" ;
+ test:Country "Canada" ;
+
+ 3151
+] .
+
+[ test:City "Daugavpils" ;
+ test:Country "Latvia" ;
+
+ 3223
+] .
+
+[ test:City "Subotica" ;
+ test:Country "Serbia" ;
+
+ 795
+] .
+
+[ test:City "Sorsogon City" ;
+ test:Country "Philippines" ;
+
+ 759
+] .
+
+[ test:City "Khandwa" ;
+ test:Country "India" ;
+
+ 1643
+] .
+
+[ test:City "Farrukhabad" ;
+ test:Country "India" ;
+
+ 2135
+] .
+
+[ test:City "Alexandra" ;
+ test:Country "South Africa" ;
+
+ 3386
+] .
+
+[ test:City "Rio Verde" ;
+ test:Country "Brazil" ;
+
+ 430
+] .
+
+[ test:City "Kütahya" ;
+ test:Country "Turkey" ;
+
+ 1770
+] .
+
+[ test:City "Tabriz" ;
+ test:Country "Iran" ;
+
+ 1806
+] .
+
+[ test:City "Chandannagar" ;
+ test:Country "India" ;
+
+ 1126
+] .
+
+[ test:City "Edmonton" ;
+ test:Country "Canada" ;
+
+ 2466
+] .
+
+[ test:City "Huddersfield" ;
+ test:Country "United Kingdom" ;
+
+ 3021
+] .
+
+[ test:City "Or Yehuda" ;
+ test:Country "Israel" ;
+
+ 38
+] .
+
+[ test:City "Shangqiu" ;
+ test:Country "China" ;
+
+ 665
+] .
+
+[ test:City "Constantine" ;
+ test:Country "Algeria" ;
+
+ 1253
+] .
+
+[ test:City "Beijing" ;
+ test:Country "China" ;
+
+ 2629
+] .
+
+[ test:City "Dijon" ;
+ test:Country "France" ;
+
+ 3256
+] .
+
+[ test:City "Milan" ;
+ test:Country "Italy" ;
+
+ 273
+] .
+
+[ test:City "Sutton Coldfield" ;
+ test:Country "United Kingdom" ;
+
+ 828
+] .
+
+[ test:City "Kinshasa" ;
+ test:Country "Democratic Republic of the Congo" ;
+
+ 1676
+] .
+
+[ test:City "Hanoi" ;
+ test:Country "Vietnam" ;
+
+ 2927
+] .
+
+[ test:City "Amiens" ;
+ test:Country "France" ;
+