Skip to content

Commit

Permalink
Show attributes of both sources (GWSW and IMBOR kern)
Browse files Browse the repository at this point in the history
  • Loading branch information
bartwr committed Nov 19, 2024
1 parent 9f0f599 commit 4a99f2f
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 46 deletions.
72 changes: 43 additions & 29 deletions app/api/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,19 +44,25 @@ export const getPhysicalObjectsForSource = async (source: Source) => {
}
}

export const getAttributesForClass = async (source: Source, classUri: string) => {
const imbor_attributes = await getImborAttributesForClass(classUri);
const gwsw_attributes = await getGwswAttributesForClass(classUri);
export const getAttributesForClass = async (activeSource: Source, classUris: any[]) => {
let attributes_per_source: any = [], head: any;
for(const classUri of classUris) {
if(classUri.indexOf('gwsw') > -1) {
const gwsw_attributes = await getGwswAttributesForClass(classUri);
head = gwsw_attributes.head;
attributes_per_source = [...attributes_per_source, ...gwsw_attributes.results?.bindings];
}
else {
const imbor_attributes = await getImborAttributesForClass(classUri);
head = imbor_attributes.head;
attributes_per_source = [...attributes_per_source, ...imbor_attributes.results?.bindings];
}
}

// Merge both objects
let merged_bindings = mergeAttributes(
gwsw_attributes.results?.bindings,
imbor_attributes.results?.bindings
);
const merged = {
head: imbor_attributes.head,
head: head,
results: {
bindings: merged_bindings
bindings: deDuplicateAttributes(attributes_per_source)
}
}

Expand All @@ -65,34 +71,42 @@ export const getAttributesForClass = async (source: Source, classUri: string) =>
}

export const getEnumsForAttribute = async (attributeUri: string) => {
const imbor_enums = await getImborEnumsForAttribute(attributeUri);
// Don't look up enums for GWSW for now
if(attributeUri.indexOf('gwsw') > -1) return;

// Merge both objects
const merged = imbor_enums;
// Get enums for attributeUri
const imbor_enums = await getImborEnumsForAttribute(attributeUri);

// And return
return merged;
return imbor_enums;
}

// mergeAttributes :: Merge attributes based on entry_text
const mergeAttributes = (bindings1: Attribute[], bindings2: Attribute[]) => {
if (!bindings1 && !bindings2) return [];
if (!bindings1) return bindings2;
if (!bindings2) return bindings1;

let merged: Attribute[] = bindings1;

// Add bindings2 entries, if not present in bindings1 dataset
bindings2.forEach((x2: Attribute) => {
const related_attribute: Attribute | undefined = bindings1.find((x1: Attribute) => x1.entry_text?.value === x2.entry_text?.value);
if(! related_attribute) merged.push(x2);
// deDuplicateAttributes :: Merge attributes based on entry_text
const deDuplicateAttributes = (attributes: any[]) => {
if (!attributes) return [];

// Create variable to store list of unique attributes in
let deDuplicated: Attribute[] = attributes;

// Create a Map to store unique entries based on entry_text.value
const uniqueMap = new Map();

// Iterate through attributes and keep only unique entries
attributes.forEach((attribute: Attribute) => {
const entryTextValue = attribute?.entry_text?.value;
if (entryTextValue && !uniqueMap.has(entryTextValue)) {
uniqueMap.set(entryTextValue, attribute);
}
});

// Convert Map values back to array
deDuplicated = Array.from(uniqueMap.values());

(() => {
// Check if 'identificatie' exists as an attribute field
const identificatie_exists = merged.find((attribute: Attribute) => attribute?.entry_text?.value === 'identificatie');
const identificatie_exists = deDuplicated.find((attribute: Attribute) => attribute?.entry_text?.value === 'identificatie');
// If not: Add 'identificatie' object to beginning of the array
if(! identificatie_exists) merged.unshift({
if(! identificatie_exists) deDuplicated.unshift({
"entry_iri": {
"type": "uri",
"value": "https://data.crow.nl/imbor/def/5f430c8d-7503-4a69-9e2f-f0b6e6c7f54e"
Expand All @@ -114,6 +128,6 @@ const mergeAttributes = (bindings1: Attribute[], bindings2: Attribute[]) => {
});
})();

return merged;
return deDuplicated;
}

54 changes: 42 additions & 12 deletions app/components/EditObject/EditObject.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ import Attribute from './Attribute';
// Import helper functions
import {
getKern,
getGeoClasses
getGeoClasses,
getPhysicalObjects
} from '../../api/imbor'
import {
getAttributesForClass,
Expand All @@ -45,7 +46,7 @@ import {

import './EditObject.css'
import SourceLabel from '../SourceLabel/SourceLabel';
import { Source } from '@/app/types';
import { PhysicalObject, Source } from '@/app/types';

interface ImborResponse {
head: object,
Expand Down Expand Up @@ -100,9 +101,30 @@ const EditObject = () => {
}

// Fetch attributes for a specific FysicalObject class
const fetchAttributesForClass = async (source: Source, classUri: URL) => {
const fetchAttributesForClass = async (activeSource: Source, classUri: URL, objectName: String) => {
if(! config) return;
if(! classUri) return;
const response = await getAttributesForClass(source, classUri);

// Define sources we want physical objects from
const sources = ['imbor_kern', 'gwsw_basis_v161'];

// Fetch physical objects for these sources
let all_physical_objects: any = [];
for(const source_id of sources) {
const source_objects = await fetchPhysicalObjects(config.sources[source_id]);
all_physical_objects = [...all_physical_objects, ...source_objects];
}

// Fetch classUri's for all physical objects having name: objectName
const relevant_objects = all_physical_objects.filter((object: PhysicalObject) => {
return object.label?.value === objectName;
});

const object_uris = relevant_objects.map((object: PhysicalObject) => {
return object.classURI?.value;
});

const response = await getAttributesForClass(activeSource, object_uris);
const triples = makeTriplesObject(response);
// Make ID the first attribute
const sortedTriples = triples.sort((a: any, b: any) => {
Expand Down Expand Up @@ -159,7 +181,7 @@ const EditObject = () => {
setGeometry(object.geometry);
}
// Fetch attributes for object type
const attributes = await fetchAttributesForClass(source, object.uri);
const attributes = await fetchAttributesForClass(source, object.uri, object.label);
// Fill in all attributes after a few milliseconds (so state can update first)
setTimeout(() => {
if(! object.attributes) return;
Expand Down Expand Up @@ -216,22 +238,30 @@ const EditObject = () => {
const source = config.sources[selectedSource.id];
if(! source) return;

const response = await getPhysicalObjectsForSource(source);
const uniqueTriples = getUniquePhysicalObjects(response.results?.bindings);
const sortedTriples = uniqueTriples.sort((a, b) => {
return a.label.value > b.label.value ? 1 : -1;
});
dispatch(setPhysicalObjects(sortedTriples))
// Fetch physical objects
const physical_objects = await fetchPhysicalObjects(source);

// Set in state
dispatch(setPhysicalObjects(physical_objects))
})();
}, [selectedSource]);

// Function that runs if selected objectType changes
useEffect(() => {
if(! selectedObjectType) return;

fetchAttributesForClass(config.sources[selectedSource.id], selectedObjectType.label);
fetchAttributesForClass(config.sources[selectedSource.id], selectedObjectType.label, selectedObjectType.value);
}, [selectedObjectType])

const fetchPhysicalObjects = async (source: Source) => {
const response = await getPhysicalObjectsForSource(source);
const uniqueTriples = getUniquePhysicalObjects(response.results?.bindings);
const sortedTriples = uniqueTriples.sort((a, b) => {
return a.label.value > b.label.value ? 1 : -1;
});
return sortedTriples;
}

// Function that prepares data to be used for DatalistInput
const prepareSourcesForDataList = (sources: any) => {
let ret: any = [];
Expand Down
2 changes: 2 additions & 0 deletions app/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const config: Config = {
name: "imbor_kern",
title: "IMBOR kern",
url: "https://hub.laces.tech/crow/imbor/2022/p/kern/sparql",
classRootUrl: "http://data.gwsw.nl/1.6/totaal/",
fetchOptions: {
method: "get",
headers: {
Expand All @@ -24,6 +25,7 @@ const config: Config = {
name: "gwsw_basis_v161",
title: "GWSW Basis v1.6.1",
url: "https://sparql.gwsw.nl/repositories/GWSW_Dataset_v161",
classRootUrl: "https://data.crow.nl/imbor/def/",
fetchOptions: {
method: "post",
headers: {
Expand Down
17 changes: 12 additions & 5 deletions app/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
type Source = {
name?: string
title?: string
url: string
fetchOptions?: any
name?: string;
title?: string;
url: string;
classRootUrl: string;
fetchOptions?: any;
};

type Sources = {
[key: string]: Source
};

type PhysicalObject = {
classURI: any;
label: any;
};

type Config = {
imbor?: any;
sources: Sources;
Expand All @@ -24,5 +30,6 @@ type Attribute = {
export type {
Config,
Source,
Attribute
Attribute,
PhysicalObject
}

0 comments on commit 4a99f2f

Please sign in to comment.