Skip to content

Add domain and range columns for Properties #866

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 10, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
255 changes: 251 additions & 4 deletions frontend/src/pages/ontologies/entities/EntityList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import DataTable, { Column } from "../../../components/DataTable";
import Entity from "../../../model/Entity";
import { getEntities } from "../ontologiesSlice";
import Individual from "../../../model/Individual";
import Property from "../../../model/Property";

export default function EntityList({
ontologyId,
Expand Down Expand Up @@ -92,11 +93,257 @@ export default function EntityList({
},
};

// Define domain column for properties
const domainColumn: Column = {
name: "Domain",
sortable: true,
selector: (entity: Entity) => {
if(entity instanceof Property) {
const domains = entity.getDomain();
if (domains && domains.length > 0) {
const linkedEntities = entity.getLinkedEntities();
return domains
.map((domain: any) => {
// Handle string IRIs
if (typeof domain === "string") {
return formatIri(domain, linkedEntities);
}

// Handle array (could be a list of domains)
if (Array.isArray(domain)) {
return domain.map((item: any) => {
if (typeof item === "string") {
return formatIri(item, linkedEntities);
}
if (typeof item === "object") {
// Handle unionOf inside an object in the array
if (item["http://www.w3.org/2002/07/owl#unionOf"] &&
Array.isArray(item["http://www.w3.org/2002/07/owl#unionOf"])) {

const unionOf = item["http://www.w3.org/2002/07/owl#unionOf"];
return unionOf.map((unionItem: any) => {
if (typeof unionItem === "string") {
return formatIri(unionItem, linkedEntities);
}
if (typeof unionItem === "object" &&
unionItem["http://www.w3.org/2002/07/owl#someValuesFrom"] &&
unionItem["http://www.w3.org/2002/07/owl#onProperty"]) {
return formatRestriction(unionItem, linkedEntities);
}
return "";
}).filter(Boolean).join(" or ");
}
}
return "";
}).filter(Boolean).join(", ");
}

// Handle complex domain objects
if (typeof domain === "object" && !Array.isArray(domain)) {
// Check for someValuesFrom restriction
if (domain["http://www.w3.org/2002/07/owl#someValuesFrom"] &&
domain["http://www.w3.org/2002/07/owl#onProperty"]) {
return formatRestriction(domain, linkedEntities);
}

// Check for unionOf
const unionOf = domain["http://www.w3.org/2002/07/owl#unionOf"];
if (unionOf && Array.isArray(unionOf)) {
return unionOf.map((item: any) => {
if (typeof item === "string") {
return formatIri(item, linkedEntities);
}
if (typeof item === "object" &&
item["http://www.w3.org/2002/07/owl#someValuesFrom"] &&
item["http://www.w3.org/2002/07/owl#onProperty"]) {
return formatRestriction(item, linkedEntities);
}
return "";
}).filter(Boolean).join(" or ");
}

// Check for owl:intersectionOf
const intersectionOf = domain["http://www.w3.org/2002/07/owl#intersectionOf"];
if (intersectionOf && Array.isArray(intersectionOf)) {
return intersectionOf.map((item: any) => {
// Handle string IRIs in the intersection
if (typeof item === "string") {
return formatIri(item, linkedEntities);
}

// Handle objects in the intersection, particularly looking for owl:oneOf
if (typeof item === "object" && !Array.isArray(item)) {
// Handle restriction in intersection
if (item["http://www.w3.org/2002/07/owl#someValuesFrom"] &&
item["http://www.w3.org/2002/07/owl#onProperty"]) {
return formatRestriction(item, linkedEntities);
}

// Handle oneOf in intersection
const oneOf = item["http://www.w3.org/2002/07/owl#oneOf"];
if (oneOf && Array.isArray(oneOf)) {
// Format the oneOf elements as a comma-separated list inside curly braces
return `{${oneOf.join(", ")}}`;
}
}

return "";
}).filter(Boolean).join(" and ");
}
}

return "";
})
.filter(Boolean)
.join(", ");
}
}
return "";
},
};

// Define range column for properties
const rangeColumn: Column = {
name: "Range",
sortable: true,
selector: (entity: Entity) => {
if(entity instanceof Property) {
const ranges = entity.getRange();
if (ranges && ranges.length > 0) {
const linkedEntities = entity.getLinkedEntities();
return ranges
.map((range: any) => {
// Handle string IRIs
if (typeof range === "string") {
return formatIri(range, linkedEntities);
}

// Handle array (could be a list of ranges)
if (Array.isArray(range)) {
return range.map((item: any) => {
if (typeof item === "string") {
return formatIri(item, linkedEntities);
}
if (typeof item === "object") {
// Handle unionOf inside an object in the array
if (item["http://www.w3.org/2002/07/owl#unionOf"] &&
Array.isArray(item["http://www.w3.org/2002/07/owl#unionOf"])) {

const unionOf = item["http://www.w3.org/2002/07/owl#unionOf"];
return unionOf.map((unionItem: any) => {
if (typeof unionItem === "string") {
return formatIri(unionItem, linkedEntities);
}
if (typeof unionItem === "object" &&
unionItem["http://www.w3.org/2002/07/owl#someValuesFrom"] &&
unionItem["http://www.w3.org/2002/07/owl#onProperty"]) {
return formatRestriction(unionItem, linkedEntities);
}
return "";
}).filter(Boolean).join(" or ");
}
}
return "";
}).filter(Boolean).join(", ");
}

// Handle complex range objects
if (typeof range === "object" && !Array.isArray(range)) {
// Check for someValuesFrom restriction
if (range["http://www.w3.org/2002/07/owl#someValuesFrom"] &&
range["http://www.w3.org/2002/07/owl#onProperty"]) {
return formatRestriction(range, linkedEntities);
}

// Check for unionOf
const unionOf = range["http://www.w3.org/2002/07/owl#unionOf"];
if (unionOf && Array.isArray(unionOf)) {
return unionOf.map((item: any) => {
if (typeof item === "string") {
return formatIri(item, linkedEntities);
}
if (typeof item === "object" &&
item["http://www.w3.org/2002/07/owl#someValuesFrom"] &&
item["http://www.w3.org/2002/07/owl#onProperty"]) {
return formatRestriction(item, linkedEntities);
}
return "";
}).filter(Boolean).join(" or ");
}

// Check for owl:intersectionOf
const intersectionOf = range["http://www.w3.org/2002/07/owl#intersectionOf"];
if (intersectionOf && Array.isArray(intersectionOf)) {
return intersectionOf.map((item: any) => {
// Handle string IRIs in the intersection
if (typeof item === "string") {
return formatIri(item, linkedEntities);
}

// Handle objects in the intersection, particularly looking for owl:oneOf
if (typeof item === "object" && !Array.isArray(item)) {
// Handle restriction in intersection
if (item["http://www.w3.org/2002/07/owl#someValuesFrom"] &&
item["http://www.w3.org/2002/07/owl#onProperty"]) {
return formatRestriction(item, linkedEntities);
}

// Handle oneOf in intersection
const oneOf = item["http://www.w3.org/2002/07/owl#oneOf"];
if (oneOf && Array.isArray(oneOf)) {
// Format the oneOf elements as a comma-separated list inside curly braces
return `{${oneOf.join(", ")}}`;
}
}

return "";
}).filter(Boolean).join(" and ");
}
}
return "";
})
.filter(Boolean)
.join(", ");
}
}
return "";
},
};

// Helper function to format someValuesFrom restrictions
const formatRestriction = (restriction: any, linkedEntities: any) => {
const someValuesFromIri = restriction["http://www.w3.org/2002/07/owl#someValuesFrom"];
const onPropertyIri = restriction["http://www.w3.org/2002/07/owl#onProperty"];

if (!someValuesFromIri || !onPropertyIri) return "";

const someValuesLabel =
linkedEntities.getLabelForIri(someValuesFromIri) ||
(typeof someValuesFromIri === "string" && someValuesFromIri.split("/").pop()) ||
someValuesFromIri;

const propertyLabel =
linkedEntities.getLabelForIri(onPropertyIri) ||
(typeof onPropertyIri === "string" && onPropertyIri.split("/").pop()) ||
onPropertyIri;

return `${propertyLabel} some ${someValuesLabel}`;
};

// Helper function to format IRIs
const formatIri = (iri: string, linkedEntities: any) => {
return linkedEntities.getLabelForIri(iri) || iri.split("/").pop() || iri;
};

// Merge columns based on the entity type.
// Merge columns based on the entity type.
const columns =
entityType === "individuals"
? [...baseColumns, individualTypeColumn]
: baseColumns;
let columns = [...baseColumns];

if (entityType === "individuals") {
columns.push(individualTypeColumn);
} else if (entityType === "properties") {
columns.push(domainColumn, rangeColumn);
}

return (
<div className="mt-2">
Expand Down
Loading