diff --git a/src/main/java/de/hbz/lobid/helper/Etikett.java b/src/main/java/de/hbz/lobid/helper/Etikett.java index a3b34271f..87651411a 100644 --- a/src/main/java/de/hbz/lobid/helper/Etikett.java +++ b/src/main/java/de/hbz/lobid/helper/Etikett.java @@ -60,7 +60,11 @@ public class Etikett { * Describes if the given is expected to occur as a \@set or a \@list. Can be * null; */ - public String container = null; + String container = null; + + String comment = null; + + String weight = null; /** * The jaxb needs this @@ -147,6 +151,48 @@ public void setReferenceType(String referenceType) { this.referenceType = referenceType; } + /** + * @return json-ld container + */ + public String getContainer() { + return container; + } + + /** + * @param container json-ld container + */ + public void setContainer(String container) { + this.container = container; + } + + /** + * @return a comment that describes the usage of the etikett + */ + public String getComment() { + return comment; + } + + /** + * @param comment a comment that describes the usage of the etikett + */ + public void setComment(String comment) { + this.comment = comment; + } + + /** + * @return a weight to order a list of etiketts + */ + public String getWeight() { + return weight; + } + + /** + * @param weight can be used to order a list of etiketts + */ + public void setWeight(String weight) { + this.weight = weight; + } + @Override public String toString() { try { diff --git a/src/main/java/de/hbz/lobid/helper/EtikettMaker.java b/src/main/java/de/hbz/lobid/helper/EtikettMaker.java index 5ae110ee4..631d25a92 100644 --- a/src/main/java/de/hbz/lobid/helper/EtikettMaker.java +++ b/src/main/java/de/hbz/lobid/helper/EtikettMaker.java @@ -19,6 +19,7 @@ License, or (at your option) any later version. import java.io.InputStream; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -33,17 +34,21 @@ License, or (at your option) any later version. * @author Jan Schnasse * */ -public class EtikettMaker { +public class EtikettMaker implements EtikettMakerInterface { + + private static final String TYPE = "type"; + + private static final String ID = "id"; final static Logger logger = LoggerFactory.getLogger(EtikettMaker.class); /** - * A map with URIs as key and labels,icons, shortnames as values + * A map with URIs as key */ Map pMap = new HashMap<>(); /** - * A map with Shortnames as key and labels,icons, uris as values + * A map with Shortnames as key */ Map nMap = new HashMap<>(); @@ -63,44 +68,50 @@ public class EtikettMaker { /** * The profile provides a json context an labels + * + * @param labelIn input stream to a labels file */ - public EtikettMaker() { + public EtikettMaker(InputStream labelIn) { + initMaps(labelIn); initContext(); - initMaps(); } - /** - * @return a map with a json-ld context + /* + * (non-Javadoc) + * + * @see de.hbz.lobid.helper.EtikettMakerInterface#getContext() */ + @Override public Map getContext() { return context; } - /** - * @param key the uri - * @return an etikett object contains uri, icon, label, jsonname, - * referenceType + /* + * (non-Javadoc) + * + * @see de.hbz.lobid.helper.EtikettMakerInterface#getEtikett(java.lang.String) */ - public Etikett getEtikett(String key) { - Etikett e = pMap.get(key); + @Override + public Etikett getEtikett(String uri) { + Etikett e = pMap.get(uri); if (e == null) { - e = new Etikett(key); - e.name = getJsonName(key); + e = new Etikett(uri); + e.name = getJsonName(uri); } - if (e.label == null) { + if (e.label == null || e.label.isEmpty()) { e.label = e.uri; } - logger.debug("Find name for " + key + " : " + e.name); + logger.debug("Find etikett for " + uri + " : " + e.name); return e; } private void initContext() { - context = createContext("context.json"); + context = createContext(); } - private void initMaps() { + private void initMaps(InputStream labelIn) { try { - labels = createLabels("labels.json"); + labels = createLabels(labelIn); for (Etikett etikett : labels) { pMap.put(etikett.uri, etikett); @@ -112,11 +123,11 @@ private void initMaps() { } - private static List createLabels(String fileName) { + private static List createLabels(InputStream labelIn) { logger.info("Create labels...."); List result = new ArrayList<>(); - result = loadFile(fileName, new ObjectMapper().getTypeFactory() + result = loadFile(labelIn, new ObjectMapper().getTypeFactory() .constructCollectionType(List.class, Etikett.class)); if (result == null) { @@ -127,28 +138,32 @@ private static List createLabels(String fileName) { return result; } - /** - * @return a Map representing additional information about the shortnames used - * in getLd - */ - Map createContext(String fileName) { - logger.info("Create context...."); - Map result = new HashMap<>(); - - result = loadFile(fileName, new ObjectMapper().getTypeFactory() - .constructMapLikeType(HashMap.class, String.class, Object.class)); - - if (result == null) { - logger.info("...not succeeded!"); - } else { - logger.info("...succeed!"); + Map createContext() { + Map pmap; + Map cmap = new HashMap<>(); + for (Etikett l : labels) { + if ("class".equals(l.referenceType) || l.referenceType == null + || l.name == null) + continue; + pmap = new HashMap<>(); + pmap.put("@id", l.uri); + if (!"String".equals(l.referenceType)) { + pmap.put("@type", l.referenceType); + } + if (l.container != null) { + pmap.put("@container", l.container); + } + cmap.put(l.name, pmap); } - return result; + cmap.put(ID, "@id"); + cmap.put(TYPE, "@type"); + Map contextObject = new HashMap<>(); + contextObject.put("@context", cmap); + return contextObject; } - private static T loadFile(String fileName, TypeBase type) { - try (InputStream in = Thread.currentThread().getContextClassLoader() - .getResourceAsStream(fileName)) { + private static T loadFile(InputStream labelIn, TypeBase type) { + try (InputStream in = labelIn) { return new ObjectMapper().readValue(in, type); } catch (Exception e) { throw new RuntimeException("Error during initialization!", e); @@ -168,4 +183,35 @@ String getJsonName(String predicate) { } return e.name; } + + @Override + public Etikett getEtikettByName(String name) { + return nMap.get(name); + } + + @Override + public Collection getValues() { + return pMap.values(); + } + + @Override + public boolean supportsLabelsForValues() { + return false; + } + + @Override + public String getIdAlias() { + return ID; + } + + @Override + public String getTypeAlias() { + return TYPE; + } + + @Override + public String getLabelKey() { + return null; + } + } diff --git a/src/main/java/de/hbz/lobid/helper/EtikettMakerInterface.java b/src/main/java/de/hbz/lobid/helper/EtikettMakerInterface.java new file mode 100644 index 000000000..72a4ee8c3 --- /dev/null +++ b/src/main/java/de/hbz/lobid/helper/EtikettMakerInterface.java @@ -0,0 +1,75 @@ +/*Copyright (c) 2016 "hbz" + +This file is part of lobid-rdf-to-json. + +etikett is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + */ +package de.hbz.lobid.helper; + +import java.util.Collection; +import java.util.Map; + +/** + * @author Jan Schnasse + * + */ +public interface EtikettMakerInterface { + + /** + * @return a map with a json-ld context + */ + Map getContext(); + + /** + * @param uri the uri + * @return an etikett object contains uri, icon, label, jsonname, + * referenceType + */ + Etikett getEtikett(String uri); + + /** + * @param name the json name + * @return an etikett object contains uri, icon, label, jsonname, + * referenceType + */ + Etikett getEtikettByName(String name); + + /** + * @return a list of all Etiketts + */ + Collection getValues(); + + /** + * @return true if the implementor provides etiketts for all kind of values + * (uris on object position). false if the implementor provides + * etiketts for fields (uris in predicate position) only. + */ + boolean supportsLabelsForValues(); + + /** + * @return the idAlias is used to substitute all occurrences of "\@id" + */ + public String getIdAlias(); + + /** + * @return the typeAlias is used to substitute all occurrences of "\@type" + */ + public String getTypeAlias(); + + /** + * @return returns a json key that is used to store label info + */ + public String getLabelKey(); + +} \ No newline at end of file diff --git a/src/main/java/de/hbz/lobid/helper/Globals.java b/src/main/java/de/hbz/lobid/helper/Globals.java deleted file mode 100644 index bdc151138..000000000 --- a/src/main/java/de/hbz/lobid/helper/Globals.java +++ /dev/null @@ -1,31 +0,0 @@ -/*Copyright (c) 2015 "hbz" - -This file is part of lobid-rdf-to-json. - -etikett is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as -published by the Free Software Foundation, either version 3 of the -License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Affero General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . - */ -package de.hbz.lobid.helper; - -/** - * @author Jan Schnasse - * - */ -public class Globals { - - /** - * Use this to read config files created with etikett - * (https://github.com/hbz/etikett) - */ - public static EtikettMaker etikette = new EtikettMaker(); -} diff --git a/src/main/java/de/hbz/lobid/helper/JsonConverter.java b/src/main/java/de/hbz/lobid/helper/JsonConverter.java index c8d8a8a98..6f789241b 100644 --- a/src/main/java/de/hbz/lobid/helper/JsonConverter.java +++ b/src/main/java/de/hbz/lobid/helper/JsonConverter.java @@ -19,6 +19,7 @@ License, or (at your option) any later version. import java.io.InputStream; import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -45,6 +46,9 @@ License, or (at your option) any later version. */ public class JsonConverter { + private String labelKey = "label"; + private String idAlias = "id"; + final static Logger logger = LoggerFactory.getLogger(JsonConverter.class); String first = "http://www.w3.org/1999/02/22-rdf-syntax-ns#first"; @@ -58,6 +62,18 @@ public class JsonConverter { private String mainSubjectOfTheResource; + private EtikettMakerInterface etikette; + private Map visited = new HashMap<>(); + + /** + * @param e An EtikettMaker provides access to labels + */ + public JsonConverter(EtikettMakerInterface e) { + etikette = e; + labelKey = etikette.getLabelKey(); + idAlias = etikette.getIdAlias(); + } + /** * You can easily convert the map to json using the object mapper provided by * {@link #getObjectMapper}. @@ -69,15 +85,38 @@ public class JsonConverter { * containing a json-ld context or a url to a json-ldContext * @return a map */ - public Map convert(InputStream in, RDFFormat format, + public Map convertLobidData(InputStream in, RDFFormat format, final String rootNodePrefix, Object context) { Graph g = RdfUtils.readRdfToGraph(in, format, ""); - collect(g); - mainSubjectOfTheResource = g.parallelStream() + String subject = g.parallelStream() .filter(triple -> triple.getPredicate().stringValue() .equals("http://www.w3.org/2007/05/powder-s#describedby")) - .filter(triple -> triple.getSubject().stringValue().startsWith(rootNodePrefix)) + .filter(triple -> triple.getSubject().stringValue() + .startsWith(rootNodePrefix)) .findFirst().get().getSubject().toString(); + return convert(subject, context, g); + } + + /** + * You can easily convert the map to json using the object mapper provided by + * {@link #getObjectMapper}. + * + * @param in an input stream containing rdf data + * @param format the rdf format + * @param subject the root subject node of the resource + * @param context to create valid json-ld you have to provide either a a map + * containing a json-ld context or a url to a json-ldContext + * @return a map + */ + public Map convert(String subject, InputStream in, + RDFFormat format, Object context) { + Graph g = RdfUtils.readRdfToGraph(in, format, ""); + return convert(subject, context, g); + } + + private Map convert(String subject, Object context, Graph g) { + mainSubjectOfTheResource = subject; + collect(g); Map result = createMap(g); result.put("@context", context); return result; @@ -86,11 +125,11 @@ public Map convert(InputStream in, RDFFormat format, private Map createMap(Graph g) { Map jsonResult = new TreeMap<>(); Iterator i = g.iterator(); - jsonResult.put("id", mainSubjectOfTheResource); + jsonResult.put(idAlias, mainSubjectOfTheResource); while (i.hasNext()) { Statement s = i.next(); if (mainSubjectOfTheResource.equals(s.getSubject().stringValue())) { - Etikett e = Globals.etikette.getEtikett(s.getPredicate().stringValue()); + Etikett e = etikette.getEtikett(s.getPredicate().stringValue()); createObject(jsonResult, s, e); } } @@ -189,12 +228,27 @@ private void addBlankNodeToJsonResult(Map jsonResult, private Map createObjectWithId(String uri) { Map newObject = new TreeMap<>(); if (uri != null) { - newObject.put("id", uri); + newObject.put(idAlias, uri); + if (etikette.supportsLabelsForValues()) { + getLabelFromEtikettMaker(uri, newObject); + } createObject(uri, newObject); } return newObject; } + private void getLabelFromEtikettMaker(String uri, + Map newObject) { + try { + String label = etikette.getEtikett(uri).label; + if (label != null && !label.isEmpty()) { + newObject.put(labelKey, label); + } + } catch (Exception e) { + logger.debug(e.getMessage()); + } + } + private Map createObjectWithoutId(String uri) { Map newObject = new TreeMap<>(); if (uri != null) { @@ -205,17 +259,31 @@ private Map createObjectWithoutId(String uri) { private void createObject(String uri, Map newObject) { for (Statement s : find(uri)) { - Etikett e = Globals.etikette.getEtikett(s.getPredicate().stringValue()); + Etikett e = etikette.getEtikett(s.getPredicate().stringValue()); if (s.getObject() instanceof org.openrdf.model.Literal) { newObject.put(e.name, s.getObject().stringValue()); } else { + if (statementVisited(s)) { + continue; + } if (!mainSubjectOfTheResource.equals(s.getObject().stringValue())) { createObject(newObject, s, e); } else { newObject.put(e.name, s.getObject().stringValue()); } } + + } + + } + + private boolean statementVisited(Statement s) { + boolean result = visited.containsKey(s); + if (result) { + logger.debug("Already visited " + s); } + visited.put(s, s); + return result; } private Set find(String uri) { diff --git a/src/test/java/TestJsonToRdfConversion.java b/src/test/java/TestJsonToRdfConversion.java index 411b04da6..281057bad 100644 --- a/src/test/java/TestJsonToRdfConversion.java +++ b/src/test/java/TestJsonToRdfConversion.java @@ -22,7 +22,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import de.hbz.lobid.helper.Globals; +import de.hbz.lobid.helper.EtikettMaker; +import de.hbz.lobid.helper.EtikettMakerInterface; import de.hbz.lobid.helper.JsonConverter; import de.hbz.lobid.helper.RdfUtils; @@ -39,6 +40,10 @@ public class TestJsonToRdfConversion { * if true, the generated n-triples will be printed to BASE+REVERSE_OUT */ private static final boolean PRINT = false; + + private static EtikettMakerInterface etikettMaker = + new EtikettMaker(Thread.currentThread().getContextClassLoader() + .getResourceAsStream("labels.json")); /** * if true all comparisons will be executed. No assertion will fail. */ @@ -212,7 +217,7 @@ private static String createJsonString(String jsonFilename) { Map jsonMap = JsonConverter.getObjectMapper() .readValue(Thread.currentThread().getContextClassLoader() .getResourceAsStream(jsonFilename), Map.class); - jsonMap.put("@context", Globals.etikette.getContext().get("@context")); + jsonMap.put("@context", etikettMaker.getContext().get("@context")); String jsonString = JsonConverter.getObjectMapper().writeValueAsString(jsonMap); return jsonString; diff --git a/src/test/java/TestRdfToJsonConversion.java b/src/test/java/TestRdfToJsonConversion.java index e90ce3f26..df4e9d701 100644 --- a/src/test/java/TestRdfToJsonConversion.java +++ b/src/test/java/TestRdfToJsonConversion.java @@ -36,7 +36,8 @@ License, or (at your option) any later version. import com.fasterxml.jackson.databind.ObjectMapper; import de.hbz.lobid.helper.CompareJsonMaps; -import de.hbz.lobid.helper.Globals; +import de.hbz.lobid.helper.EtikettMaker; +import de.hbz.lobid.helper.EtikettMakerInterface; import de.hbz.lobid.helper.JsonConverter; /** @@ -54,12 +55,15 @@ License, or (at your option) any later version. */ public class TestRdfToJsonConversion { + private static EtikettMakerInterface etikettMaker = + new EtikettMaker(Thread.currentThread().getContextClassLoader() + .getResourceAsStream("labels.json")); final static Logger logger = LoggerFactory.getLogger(TestRdfToJsonConversion.class); final static String LOBID_RESOURCES_URI_PREFIX = "http://lobid.org/resource/"; @SuppressWarnings("unchecked") final static Map fullContext = - (Map) Globals.etikette.getContext().get("@context"); + (Map) etikettMaker.getContext().get("@context"); final static String contextUrl = "http://lobid.org/context/lobid-resources.json"; @@ -105,12 +109,13 @@ private static boolean testFiles(String fnameNtriples, String fnameJson, String uri) { Map expected = null; Map actual = null; - TestRdfToJsonConversion.logger.info("New test, begin converting files"); + TestRdfToJsonConversion.logger + .info("Convert " + fnameNtriples + " to " + fnameJson); try (InputStream in = new FileInputStream(new File(fnameNtriples)); InputStream out = new File(fnameJson).exists() ? new FileInputStream(new File(fnameJson)) : makeFile(fnameJson)) { - actual = - new JsonConverter().convert(in, RDFFormat.NTRIPLES, uri, contextUrl); + actual = new JsonConverter(etikettMaker).convertLobidData(in, + RDFFormat.NTRIPLES, uri, contextUrl); TestRdfToJsonConversion.logger.debug("Creates: "); TestRdfToJsonConversion.logger .debug(new ObjectMapper().writeValueAsString(actual)); diff --git a/src/test/resources/input/nt/00507/HT005077920.nt b/src/test/resources/input/nt/00507/HT005077920.nt new file mode 100644 index 000000000..4359f5cb0 --- /dev/null +++ b/src/test/resources/input/nt/00507/HT005077920.nt @@ -0,0 +1,45 @@ + . + "20060320"^^ . + "19991118"^^ . + "Zeitschrift"^^ . + "Zeitschrift"^^ . + "HITEE"^^ . + "Industrielle Technik"^^ . + "Routledge"^^ . + . + . + . + "Regionalgeschichte"^^ . + "Germantown, NY : Periodical Service Co."^^ . + "07341512"^^ . + "Technik | Geschichte | Zeitschrift"^^ . + . + . + "47030-2"^^ . + "1983 - "^^ . + "Zeitgeschichte"^^ . + "Periodikum"^^ . + . + "Ortsgeschichte"^^ . + . + "HITEEB"^^ . + . + "Abingdon; Routledge; 1983"^^ . + . + "Landesgeschichte"^^ . + "HT005077920"^^ . + . + . + "Abingdon"^^ . + "Hist Technol"^^ . + . + "Zeitschriften"^^ . + . + "HT ; an international journal"^^ . + "History and technology"^^ . + . + . + "Geschichte"^^ . + "Geschichte"^^ . + "Technik"^^ . + "Technik"^^ . diff --git a/src/test/resources/output/json/00507/HT005077920.json b/src/test/resources/output/json/00507/HT005077920.json new file mode 100644 index 000000000..eb6276320 --- /dev/null +++ b/src/test/resources/output/json/00507/HT005077920.json @@ -0,0 +1,62 @@ +{ + "@context" : "http://lobid.org/context/lobid-resources.json", + "describedby" : [ { + "id" : "http://lobid.org/resource/HT005077920/about" + } ], + "edition" : [ "Germantown, NY : Periodical Service Co." ], + "exemplar" : [ { + "id" : "http://lobid.org/item/HT005077920:DE-294-11:Z%201023" + }, { + "id" : "http://lobid.org/item/HT005077920:DE-361:14%20CA000%20H870" + } ], + "hbzId" : [ "HT005077920" ], + "id" : "http://lobid.org/resource/HT005077920", + "isPrimaryTopicOf" : [ { + "id" : "http://193.30.112.134/F/?func=find-c&ccl_term=IDN%3DHT005077920" + } ], + "issn" : [ "07341512" ], + "issued" : [ "1983 - " ], + "language" : [ { + "id" : "http://id.loc.gov/vocabulary/iso639-2/eng" + } ], + "medium" : [ { + "id" : "http://rdvocab.info/termList/RDAproductionMethod/1010" + } ], + "otherTitleInformation" : [ "HT ; an international journal" ], + "placeOfPublication" : [ "Abingdon" ], + "publicationStatement" : [ "Abingdon; Routledge; 1983" ], + "publisher" : [ "Routledge" ], + "sameAs" : [ { + "id" : "http://ld.zdb-services.de/resource/47030-2" + }, { + "describedby" : [ { + "dateCreated" : "19991118", + "dateModified" : "20060320", + "id" : "http://lobid.org/resource/ZDB47030-2/about", + "primaryTopic" : [ { + "id" : "http://lobid.org/resource/ZDB47030-2", + "sameAs" : "http://lobid.org/resource/HT005077920" + } ] + } ], + "id" : "http://lobid.org/resource/ZDB47030-2" + } ], + "shortTitle" : [ "Hist Technol", "HITEEB", "HITEE" ], + "subject" : [ { + "id" : "http://d-nb.info/gnd/4020517-4", + "preferredName" : "Geschichte", + "preferredNameForTheSubjectHeading" : "Geschichte" + }, { + "id" : "http://d-nb.info/gnd/4059205-4", + "preferredName" : "Technik", + "preferredNameForTheSubjectHeading" : "Technik" + }, { + "id" : "http://d-nb.info/gnd/4067488-5", + "preferredName" : "Zeitschrift", + "preferredNameForTheSubjectHeading" : "Zeitschrift" + } ], + "subjectChain" : [ "Technik | Geschichte | Zeitschrift" ], + "subjectLabel" : [ "Industrielle Technik", "Zeitschriften", "Landesgeschichte", "Ortsgeschichte", "Periodikum", "Zeitgeschichte", "Regionalgeschichte" ], + "title" : [ "History and technology" ], + "type" : [ "http://purl.org/ontology/bibo/Journal", "http://purl.org/dc/terms/BibliographicResource" ], + "zdbId" : [ "47030-2" ] +} \ No newline at end of file