Skip to content

Commit

Permalink
#258 : add referencePublication to externalDataSoftware
Browse files Browse the repository at this point in the history
  • Loading branch information
guillermau committed Jan 17, 2025
1 parent c508bcb commit 40f686a
Show file tree
Hide file tree
Showing 11 changed files with 111 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const createPgSoftwareExternalDataRepository = (db: Kysely<Database>): So
keywords: JSON.stringify(softwareExternalData.keywords),
applicationCategories: JSON.stringify(softwareExternalData.applicationCategories),
programmingLanguages: JSON.stringify(softwareExternalData.programmingLanguages),
referencePublication: JSON.stringify(softwareExternalData.referencePublication),
description: JSON.stringify(softwareExternalData.description)
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ export const createPgSoftwareRepository = (db: Kysely<Database>): SoftwareReposi
parentWikidataSoftware: parentExternalData,
keywords: software?.keywords ?? softwareExternalData?.keywords ?? [],
programmingLanguages: softwareExternalData?.programmingLanguages ?? [],
referencePublication: softwareExternalData?.referencePublication,
applicationCategories: software.categories.concat(
softwareExternalData?.applicationCategories ?? []
),
Expand Down Expand Up @@ -294,7 +295,8 @@ export const createPgSoftwareRepository = (db: Kysely<Database>): SoftwareReposi
softwareExternalData?.applicationCategories ?? []
),
categories: undefined, // merged in applicationCategories, set to undefined to remove it
programmingLanguages: softwareExternalData?.programmingLanguages ?? []
programmingLanguages: softwareExternalData?.programmingLanguages ?? [],
referencePublication: softwareExternalData?.referencePublication
});
}
);
Expand Down Expand Up @@ -429,6 +431,7 @@ const makeGetSoftwareBuilder = (db: Kysely<Database>) =>
documentationUrl: ref("ext.documentationUrl"),
programmingLanguages: ref("ext.programmingLanguages"),
applicationCategories: ref("ext.applicationCategories"),
referencePublication: ref("ext.referencePublication"),
keywords: ref("ext.keywords"),
softwareVersion: ref("ext.softwareVersion"),
publicationTime: ref("ext.publicationTime")
Expand Down Expand Up @@ -562,6 +565,7 @@ const makeGetSoftwareById =
testUrl: testUrls[0]?.url,
parentWikidataSoftware: parentExternalData,
programmingLanguages: softwareExternalData?.programmingLanguages ?? [],
referencePublication: softwareExternalData?.referencePublication,
applicationCategories: filterDuplicate(
software.categories.concat(softwareExternalData?.applicationCategories ?? [])
),
Expand Down
2 changes: 2 additions & 0 deletions api/src/core/adapters/dbApi/kysely/kysely.database.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Generated, JSONColumnType } from "kysely";
import { AuthStructure } from "../../../ports/GetSoftwareExternalData";
import { ScholarlyArticle } from "../../../../types/codemeta";

export type Database = {
agents: AgentsTable;
Expand Down Expand Up @@ -84,6 +85,7 @@ type SoftwareExternalDatasTable = {
keywords: JSONColumnType<string[]> | null;
programmingLanguages: JSONColumnType<string[]> | null;
applicationCategories: JSONColumnType<string[]> | null;
referencePublication: JSONColumnType<ScholarlyArticle[]> | null;
publicationTime: Date | null;
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Kysely } from "kysely";

export async function up(db: Kysely<any>): Promise<void> {
await db.schema.alterTable("software_external_datas").addColumn("referencePublication", "jsonb").execute();
}

export async function down(db: Kysely<any>): Promise<void> {
await db.schema.alterTable("software_external_datas").dropColumn("referencePublication").execute();
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ const softwareExternalData: SoftwareExternalData = {
keywords: ["Usefull", "Daily"],
programmingLanguages: ["C++"],
applicationCategories: ["Software Cat I", "Software Cat II"],
referencePublication: undefined,
publicationTime: new Date(1561566581000)
};

Expand All @@ -74,6 +75,7 @@ const similarSoftwareExternalData: SoftwareExternalData = {
keywords: ["Infra", "Adminsys"],
programmingLanguages: ["Python3"],
applicationCategories: ["Software Cat I", "Software Cat II"],
referencePublication: undefined,
publicationTime: new Date(1561566581000)
};

Expand Down Expand Up @@ -433,9 +435,10 @@ describe("pgDbApi", () => {
developers: JSON.stringify(softExtData.developers),
label: JSON.stringify(softExtData.label),
description: JSON.stringify(softExtData.description),
keywords: JSON.stringify(softwareExternalData.keywords),
applicationCategories: JSON.stringify(softwareExternalData.applicationCategories),
programmingLanguages: JSON.stringify(softwareExternalData.programmingLanguages)
keywords: JSON.stringify(softExtData.keywords),
applicationCategories: JSON.stringify(softExtData.applicationCategories),
programmingLanguages: JSON.stringify(softExtData.programmingLanguages),
referencePublication: JSON.stringify(softExtData.referencePublication)
}))
)
.execute();
Expand Down
4 changes: 4 additions & 0 deletions api/src/core/adapters/fetchExternalData.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ describe("fetches software extra data (from different providers)", () => {
sourceUrl: "https://github.com/facebook/create-react-app",
websiteUrl: "https://create-react-app.dev/",
programmingLanguages: [],
referencePublication: null,
softwareVersion: "5.0.1",
publicationTime: new Date("2022-04-12T00:00:00.000Z")
},
Expand All @@ -212,6 +213,7 @@ describe("fetches software extra data (from different providers)", () => {
externalId: "Q111590996",
framaLibreId: null,
isLibreSoftware: true,

keywords: [],
label: "Vite",
license: "MIT licence",
Expand All @@ -220,6 +222,7 @@ describe("fetches software extra data (from different providers)", () => {
sourceUrl: "https://github.com/vitejs/vite",
websiteUrl: "https://vitejs.dev/",
programmingLanguages: ["JavaScript"],
referencePublication: null,
softwareVersion: expect.any(String),
publicationTime: expect.any(Date)
}
Expand Down Expand Up @@ -276,6 +279,7 @@ describe("fetches software extra data (from different providers)", () => {
"//upload.wikimedia.org/wikipedia/commons/thumb/1/10/Apache_HTTP_server_logo_%282019-present%29.svg/220px-Apache_HTTP_server_logo_%282019-present%29.svg.png",
sourceUrl: "https://github.com/apache/httpd",
websiteUrl: "https://httpd.apache.org/",
referencePublication: null,
programmingLanguages: ["C"],
softwareVersion: "2.5.0-alpha",
publicationTime: new Date("2017-11-08T00:00:00.000Z")
Expand Down
1 change: 1 addition & 0 deletions api/src/core/adapters/hal/getHalSoftware.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ describe("HAL", () => {
"keywords": undefined,
"programmingLanguages": undefined,
"applicationCategories": ["Computer Science [cs]"],
"referencePublication": undefined,
"publicationTime": new Date(1561566581000)
});
});
Expand Down
67 changes: 66 additions & 1 deletion api/src/core/adapters/hal/getHalSoftwareExternalData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { AuthStructure, GetSoftwareExternalData, SoftwareExternalData } from "..
import { fetchHalSoftwareById } from "./HalAPI/getHalSoftware";
import { halAPIGateway } from "./HalAPI";
import { HalFetchError } from "./HalAPI/type";
import { ScholarlyArticle } from "../../../types/codemeta";

const buildParentStructureTree = async (
structureIdArray: number[] | string[] | undefined
Expand All @@ -26,6 +27,69 @@ const buildParentStructureTree = async (
);
};

const parseReferencePublication = (key: string, value: string | string[]): ScholarlyArticle[] => {
const arrayValue = typeof value === "string" ? value.split(",") : value;
switch (key) {
case "hal":
return arrayValue.map((halThing): ScholarlyArticle => {
return {
"@id": halThing,
"@type": "ScholarlyArticle",
identifier: {
"@type": "PropertyValue",
value: halThing,
propertyID: "HAL",
url: halThing.includes("https") ? new URL(halThing) : new URL(`https://hal.science/${halThing}`)
}
};
});
case "doi":
return arrayValue.map((doi): ScholarlyArticle => {
return {
"@id": doi,
"@type": "ScholarlyArticle",
identifier: {
"@type": "PropertyValue",
value: doi,
propertyID: "doi",
url: doi.includes("https") ? URL.parse(doi) : URL.parse(`https://doi.org/${doi}`)
}
};
});
case "arxiv":
return arrayValue.map((arxivId): ScholarlyArticle => {
return {
"@id": arxivId,
"@type": "ScholarlyArticle",
identifier: {
"@type": "PropertyValue",
value: arxivId,
propertyID: "arxiv",
url: arxivId.includes("https")
? URL.parse(arxivId)
: URL.parse(`https://arxiv.org/abs/${arxivId}`)
}
};
});
default:
return [];
}
};

const codeMetaToReferencePublication = (HALReferencePublication: string[] | Object | undefined) => {
if (HALReferencePublication) {
if (Array.isArray(HALReferencePublication)) {
console.error("Issue with HAL data. This data need to be curated", HALReferencePublication);
return undefined;
}

return Object.entries(HALReferencePublication).reduce((publicationArray: ScholarlyArticle[], [key, value]) => {
return publicationArray.concat(parseReferencePublication(key, value));
}, []);
}
return undefined;
};

export const getHalSoftwareExternalData: GetSoftwareExternalData = memoize(
async (halDocId): Promise<SoftwareExternalData | undefined> => {
const halRawSoftware = await fetchHalSoftwareById(halDocId).catch(error => {
Expand Down Expand Up @@ -121,7 +185,8 @@ export const getHalSoftwareExternalData: GetSoftwareExternalData = memoize(
applicationCategories: sciencesCategories,
publicationTime: halRawSoftware?.modifiedDate_tdate
? new Date(halRawSoftware?.modifiedDate_tdate)
: undefined
: undefined,
referencePublication: codeMetaToReferencePublication(codemetaSoftware.referencePublication)
};
},
{
Expand Down
1 change: 1 addition & 0 deletions api/src/core/adapters/wikidata/getWikidataSoftware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ export const getWikidataSoftware: GetSoftwareExternalData = memoize(
keywords: getClaimDataValue<"string">("P921"),
programmingLanguages: programmingLanguageString ? [programmingLanguageString] : [],
applicationCategories: undefined, // doesn't exit on wiki data
referencePublication: undefined, // doesn't exit on wiki data
publicationTime: publicationTimeDate
};
},
Expand Down
2 changes: 2 additions & 0 deletions api/src/core/ports/GetSoftwareExternalData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { z } from "zod";
import type { LocalizedString as LocalizedString_generic } from "i18nifty/LocalizedString/reactless";
import type { PartialNoOptional } from "../../tools/PartialNoOptional";
import { assert, type Equals } from "tsafe/assert";
import { ScholarlyArticle } from "../../types/codemeta";

type ExternalId = string;

Expand Down Expand Up @@ -42,6 +43,7 @@ export type SoftwareExternalData = {
programmingLanguages: string[];
applicationCategories: string[];
publicationTime: Date;
referencePublication: ScholarlyArticle[];
}>;

export type SimilarSoftwareExternalData = Pick<
Expand Down
14 changes: 14 additions & 0 deletions api/src/types/codemeta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export type CodeMeta = {
softwareVersion: string;
dateModified: string;
contributor: Auth[];
referencePublication?: string[] | string | Object;
};

export interface Role extends CodeMeta {
Expand Down Expand Up @@ -50,3 +51,16 @@ export interface SoftwareApplication extends CodeMeta {
"@type": "SoftwareApplication";
author: Auth[];
}

export type ScholarlyArticle = {
"@id": string;
"@type": "ScholarlyArticle";
identifier?: PropertyValue;
};

export type PropertyValue = {
"@type"?: "PropertyValue";
value?: string;
propertyID?: string;
url?: URL | null;
};

0 comments on commit 40f686a

Please sign in to comment.