From d9355c05fab1ada7eb4530d42f091651b7081403 Mon Sep 17 00:00:00 2001 From: Martin Ledvinka Date: Tue, 2 Aug 2022 14:19:25 +0200 Subject: [PATCH] [#163] Handle vocabulary IRI diferent from context in TermDao and snapshot creation queries. --- .../kbss/termit/persistence/dao/TermDao.java | 284 +++++++++--------- .../snapshot/CascadingSnapshotCreator.java | 2 +- src/main/resources/query/snapshot/term.ru | 3 +- .../resources/query/snapshot/vocabulary.ru | 2 +- 4 files changed, 152 insertions(+), 139 deletions(-) diff --git a/src/main/java/cz/cvut/kbss/termit/persistence/dao/TermDao.java b/src/main/java/cz/cvut/kbss/termit/persistence/dao/TermDao.java index d4d735694..267ab39bc 100644 --- a/src/main/java/cz/cvut/kbss/termit/persistence/dao/TermDao.java +++ b/src/main/java/cz/cvut/kbss/termit/persistence/dao/TermDao.java @@ -27,6 +27,7 @@ import cz.cvut.kbss.termit.model.Vocabulary; import cz.cvut.kbss.termit.model.util.HasIdentifier; import cz.cvut.kbss.termit.persistence.context.DescriptorFactory; +import cz.cvut.kbss.termit.persistence.context.VocabularyContextMapper; import cz.cvut.kbss.termit.persistence.dao.util.Cache; import cz.cvut.kbss.termit.persistence.dao.util.SparqlResultToTermInfoMapper; import cz.cvut.kbss.termit.persistence.snapshot.AssetSnapshotLoader; @@ -51,12 +52,15 @@ public class TermDao extends AssetDao implements SnapshotProvider { private final Comparator termInfoComparator; + private final VocabularyContextMapper contextMapper; + @Autowired public TermDao(EntityManager em, Configuration config, DescriptorFactory descriptorFactory, - Cache> subTermsCache) { + Cache> subTermsCache, VocabularyContextMapper contextMapper) { super(Term.class, em, config.getPersistence(), descriptorFactory); this.subTermsCache = subTermsCache; this.termInfoComparator = Comparator.comparing(t -> t.getLabel().get(config.getPersistence().getLanguage())); + this.contextMapper = contextMapper; } @Override @@ -94,12 +98,12 @@ private Set loadInverseRelatedTerms(Term term) { private Set loadTermInfo(Term term, String property, Collection exclude) { final List inverse = em.createNativeQuery("SELECT ?inverse ?label ?vocabulary WHERE {" + - "?inverse ?property ?term ;" + - "a ?type ;" + - "?hasLabel ?label ;" + - "?inVocabulary ?vocabulary . " + - "FILTER (?inverse NOT IN (?exclude))" + - "} ORDER BY ?inverse") + "?inverse ?property ?term ;" + + "a ?type ;" + + "?hasLabel ?label ;" + + "?inVocabulary ?vocabulary . " + + "FILTER (?inverse NOT IN (?exclude))" + + "} ORDER BY ?inverse") .setParameter("property", URI.create(property)) .setParameter("term", term) .setParameter("type", typeUri) @@ -195,15 +199,15 @@ private void setTermDraftStatusTo(Term term, boolean draft) { em.getEntityManagerFactory().getCache().evict(Term.class, term.getUri(), null); em.getEntityManagerFactory().getCache().evict(TermDto.class, term.getUri(), null); em.createNativeQuery("DELETE {" + - "?t ?hasStatus ?oldDraft ." + - "} INSERT {" + - "GRAPH ?g {" + - "?t ?hasStatus ?newDraft ." + - "}} WHERE {" + - "OPTIONAL {?t ?hasStatus ?oldDraft .}" + - "GRAPH ?g {" + - "?t ?inScheme ?glossary ." + - "}}").setParameter("t", term) + "?t ?hasStatus ?oldDraft ." + + "} INSERT {" + + "GRAPH ?g {" + + "?t ?hasStatus ?newDraft ." + + "}} WHERE {" + + "OPTIONAL {?t ?hasStatus ?oldDraft .}" + + "GRAPH ?g {" + + "?t ?inScheme ?glossary ." + + "}}").setParameter("t", term) .setParameter("hasStatus", URI.create(cz.cvut.kbss.termit.util.Vocabulary.s_p_je_draft)) .setParameter("inScheme", URI.create(SKOS.IN_SCHEME)) .setParameter("newDraft", draft).executeUpdate(); @@ -233,26 +237,31 @@ public List findAll(Vocabulary vocabulary) { Objects.requireNonNull(vocabulary); try { return executeQueryAndLoadSubTerms(em.createNativeQuery("SELECT DISTINCT ?term WHERE {" + - "GRAPH ?vocabulary { " + - "?term a ?type ;" + - "?hasLabel ?label ;" + - "FILTER (lang(?label) = ?labelLang) ." + - "}" + - "?term ?inVocabulary ?vocabulary ." + - " } ORDER BY " + orderSentence( + "GRAPH ?context { " + + "?term a ?type ;" + + "?hasLabel ?label ;" + + "FILTER (lang(?label) = ?labelLang) ." + + "}" + + "?term ?inVocabulary ?vocabulary ." + + " } ORDER BY " + orderSentence( config.getLanguage(), "?label"), TermDto.class) + .setParameter("context", context(vocabulary)) .setParameter("type", typeUri) .setParameter("vocabulary", vocabulary) .setParameter("hasLabel", LABEL_PROP) .setParameter("inVocabulary", - URI.create( - cz.cvut.kbss.termit.util.Vocabulary.s_p_je_pojmem_ze_slovniku)) + URI.create( + cz.cvut.kbss.termit.util.Vocabulary.s_p_je_pojmem_ze_slovniku)) .setParameter("labelLang", config.getLanguage())); } catch (RuntimeException e) { throw new PersistenceException(e); } } + private URI context(Vocabulary vocabulary) { + return contextMapper.getVocabularyContext(vocabulary); + } + /** * Gets all terms on the specified vocabulary. *

@@ -269,20 +278,21 @@ public List findAllFull(Vocabulary vocabulary) { // The workaround relies clearing the EntityManager after loading each term // The price for this solution is that this method performs very poorly for larger vocabularies (hundreds of terms) final List termIris = em.createNativeQuery("SELECT DISTINCT ?term WHERE {" + - "GRAPH ?vocabulary { " + - "?term a ?type ;" + - "?hasLabel ?label ;" + - "FILTER (lang(?label) = ?labelLang) ." + - "}" + - "?term ?inVocabulary ?vocabulary ." + - " } ORDER BY " + orderSentence(config.getLanguage(), - "?label"), URI.class) + "GRAPH ?context { " + + "?term a ?type ;" + + "?hasLabel ?label ;" + + "FILTER (lang(?label) = ?labelLang) ." + + "}" + + "?term ?inVocabulary ?vocabulary ." + + " } ORDER BY " + orderSentence(config.getLanguage(), + "?label"), URI.class) .setParameter("type", typeUri) + .setParameter("context", context(vocabulary)) .setParameter("vocabulary", vocabulary.getUri()) .setParameter("hasLabel", LABEL_PROP) .setParameter("inVocabulary", - URI.create( - cz.cvut.kbss.termit.util.Vocabulary.s_p_je_pojmem_ze_slovniku)) + URI.create( + cz.cvut.kbss.termit.util.Vocabulary.s_p_je_pojmem_ze_slovniku)) .setParameter("labelLang", config.getLanguage()).getResultList(); return termIris.stream().map(ti -> { final Term t = find(ti).get(); @@ -304,16 +314,17 @@ public boolean isEmpty(Vocabulary vocabulary) { Objects.requireNonNull(vocabulary); try { return !em.createNativeQuery("ASK WHERE {" + - "GRAPH ?vocabulary { " + - "?term a ?type ;" + - "}" + - "?term ?inVocabulary ?vocabulary ." + - " }", Boolean.class) + "GRAPH ?context { " + + "?term a ?type ;" + + "}" + + "?term ?inVocabulary ?vocabulary ." + + " }", Boolean.class) .setParameter("type", typeUri) + .setParameter("context", context(vocabulary)) .setParameter("vocabulary", vocabulary.getUri()) .setParameter("inVocabulary", - URI.create( - cz.cvut.kbss.termit.util.Vocabulary.s_p_je_pojmem_ze_slovniku)) + URI.create( + cz.cvut.kbss.termit.util.Vocabulary.s_p_je_pojmem_ze_slovniku)) .getSingleResult(); } catch (RuntimeException e) { throw new PersistenceException(e); @@ -335,21 +346,21 @@ private List executeQueryAndLoadSubTerms(TypedQuery< public List findAllIncludingImported(Vocabulary vocabulary) { Objects.requireNonNull(vocabulary); TypedQuery query = em.createNativeQuery("SELECT DISTINCT ?term WHERE {" + - "?term a ?type ;" + - "?hasLabel ?label ;" + - "?inVocabulary ?parent ." + - "?vocabulary ?imports* ?parent ." + - "FILTER (lang(?label) = ?labelLang) ." + - "} ORDER BY " + orderSentence(config.getLanguage(), - "?label"), TermDto.class) + "?term a ?type ;" + + "?hasLabel ?label ;" + + "?inVocabulary ?parent ." + + "?vocabulary ?imports* ?parent ." + + "FILTER (lang(?label) = ?labelLang) ." + + "} ORDER BY " + orderSentence(config.getLanguage(), + "?label"), TermDto.class) .setParameter("type", typeUri) .setParameter("hasLabel", LABEL_PROP) .setParameter("inVocabulary", - URI.create( - cz.cvut.kbss.termit.util.Vocabulary.s_p_je_pojmem_ze_slovniku)) + URI.create( + cz.cvut.kbss.termit.util.Vocabulary.s_p_je_pojmem_ze_slovniku)) .setParameter("imports", - URI.create( - cz.cvut.kbss.termit.util.Vocabulary.s_p_importuje_slovnik)) + URI.create( + cz.cvut.kbss.termit.util.Vocabulary.s_p_importuje_slovnik)) .setParameter("vocabulary", vocabulary) .setParameter("labelLang", config.getLanguage()); return executeQueryAndLoadSubTerms(query); @@ -372,10 +383,10 @@ private Set getSubTerms(HasIdentifier parent) { */ private Set loadSubTerms(URI parentUri) { final List subTerms = em.createNativeQuery("SELECT ?entity ?label ?vocabulary WHERE {" + - "?parent ?narrower ?entity ." + - "?entity a ?type ;" + - "?hasLabel ?label ;" + - "?inVocabulary ?vocabulary . } ORDER BY ?entity") + "?parent ?narrower ?entity ." + + "?entity a ?type ;" + + "?hasLabel ?label ;" + + "?inVocabulary ?vocabulary . } ORDER BY ?entity") .setParameter("type", typeUri) .setParameter("narrower", URI.create(SKOS.NARROWER)) .setParameter("parent", parentUri) @@ -401,19 +412,20 @@ public List findAllRoots(Vocabulary vocabulary, Pageable pageSpec, Coll Objects.requireNonNull(vocabulary); Objects.requireNonNull(pageSpec); TypedQuery query = em.createNativeQuery("SELECT DISTINCT ?term WHERE {" + - "GRAPH ?vocabulary { " + - "?term a ?type ;" + - "?hasLabel ?label ." + - "?vocabulary ?hasGlossary/?hasTerm ?term ." + - "FILTER (lang(?label) = ?labelLang) ." + - "FILTER (?term NOT IN (?included))" + - "}} ORDER BY " + orderSentence(config.getLanguage(), - "?label"), - TermDto.class); + "GRAPH ?context { " + + "?term a ?type ;" + + "?hasLabel ?label ." + + "?vocabulary ?hasGlossary/?hasTerm ?term ." + + "FILTER (lang(?label) = ?labelLang) ." + + "FILTER (?term NOT IN (?included))" + + "}} ORDER BY " + orderSentence(config.getLanguage(), + "?label"), + TermDto.class); query = setCommonFindAllRootsQueryParams(query, false); try { final List result = executeQueryAndLoadSubTerms( - query.setParameter("vocabulary", vocabulary.getUri()) + query.setParameter("context", context(vocabulary)) + .setParameter("vocabulary", vocabulary.getUri()) .setParameter("labelLang", config.getLanguage()) .setParameter("included", includeTerms) .setMaxResults(pageSpec.getPageSize()) @@ -429,20 +441,20 @@ private String orderSentence(String lang, String var) { if ("cs".equals(lang)) { return r(r(r(r(r(r(r(r(r(r(r(r(r(r("lcase(" + var + ")", - "'á'", "'azz'"), - "'č'", "'czz'"), - "'ď'", "'dzz'"), - "'é'", "'ezz'"), - "'ě'", "'ezz'"), - "'í'", "'izz'"), - "'ň'", "'nzz'"), - "'ó'", "'ozz'"), - "'ř'", "'rzz'"), - "'š'", "'szz'"), - "'ť'", "'tzz'"), - "'ú'", "'uzz'"), - "'ý'", "'yzz'"), - "'ž'", "'zzz'"); + "'á'", "'azz'"), + "'č'", "'czz'"), + "'ď'", "'dzz'"), + "'é'", "'ezz'"), + "'ě'", "'ezz'"), + "'í'", "'izz'"), + "'ň'", "'nzz'"), + "'ó'", "'ozz'"), + "'ř'", "'rzz'"), + "'š'", "'szz'"), + "'ť'", "'tzz'"), + "'ú'", "'uzz'"), + "'ý'", "'yzz'"), + "'ž'", "'zzz'"); } return "lcase(" + var + ")"; } @@ -462,15 +474,15 @@ private String r(String string, String from, String to) { public List findAllRoots(Pageable pageSpec, Collection includeTerms) { Objects.requireNonNull(pageSpec); TypedQuery query = em.createNativeQuery("SELECT DISTINCT ?term WHERE {" + - "?term a ?type ; " + - "?hasLabel ?label . " + - "?vocabulary ?hasGlossary/?hasTerm ?term . " + - "FILTER (lang(?label) = ?labelLang) . " + - "FILTER (?term NOT IN (?included)) . " + - "FILTER NOT EXISTS {?term a ?snapshot .} " + - "} ORDER BY " + orderSentence(config.getLanguage(), - "?label"), - TermDto.class); + "?term a ?type ; " + + "?hasLabel ?label . " + + "?vocabulary ?hasGlossary/?hasTerm ?term . " + + "FILTER (lang(?label) = ?labelLang) . " + + "FILTER (?term NOT IN (?included)) . " + + "FILTER NOT EXISTS {?term a ?snapshot .} " + + "} ORDER BY " + orderSentence(config.getLanguage(), + "?label"), + TermDto.class); query = setCommonFindAllRootsQueryParams(query, false); try { final List result = executeQueryAndLoadSubTerms( @@ -490,7 +502,7 @@ private TypedQuery setCommonFindAllRootsQueryParams(TypedQuery query, final TypedQuery tq = query.setParameter("type", typeUri) .setParameter("hasLabel", LABEL_PROP) .setParameter("hasGlossary", - URI.create(cz.cvut.kbss.termit.util.Vocabulary.s_p_ma_glosar)) + URI.create(cz.cvut.kbss.termit.util.Vocabulary.s_p_ma_glosar)) .setParameter("hasTerm", URI.create(SKOS.HAS_TOP_CONCEPT)); if (includeImports) { tq.setParameter("imports", URI.create(cz.cvut.kbss.termit.util.Vocabulary.s_p_importuje_slovnik)); @@ -536,15 +548,15 @@ public List findAllRootsIncludingImports(Vocabulary vocabulary, Pageabl Objects.requireNonNull(vocabulary); Objects.requireNonNull(pageSpec); TypedQuery query = em.createNativeQuery("SELECT DISTINCT ?term WHERE {" + - "?term a ?type ;" + - "?hasLabel ?label ." + - "?vocabulary ?imports* ?parent ." + - "?parent ?hasGlossary/?hasTerm ?term ." + - "FILTER (lang(?label) = ?labelLang) ." + - "FILTER (?term NOT IN (?included))" + - "} ORDER BY " + orderSentence(config.getLanguage(), - "?label"), - TermDto.class); + "?term a ?type ;" + + "?hasLabel ?label ." + + "?vocabulary ?imports* ?parent ." + + "?parent ?hasGlossary/?hasTerm ?term ." + + "FILTER (lang(?label) = ?labelLang) ." + + "FILTER (?term NOT IN (?included))" + + "} ORDER BY " + orderSentence(config.getLanguage(), + "?label"), + TermDto.class); query = setCommonFindAllRootsQueryParams(query, true); try { final List result = executeQueryAndLoadSubTerms( @@ -573,15 +585,16 @@ public List findAll(String searchString, Vocabulary vocabulary) { Objects.requireNonNull(searchString); Objects.requireNonNull(vocabulary); final TypedQuery query = em.createNativeQuery("SELECT DISTINCT ?term WHERE {" + - "GRAPH ?vocabulary { " + - "?term a ?type ; " + - " ?hasLabel ?label ; " + - "FILTER CONTAINS(LCASE(?label), LCASE(?searchString)) ." + - "}" + - "?term ?inVocabulary ?vocabulary ." + - "} ORDER BY " + orderSentence( + "GRAPH ?context { " + + "?term a ?type ; " + + " ?hasLabel ?label ; " + + "FILTER CONTAINS(LCASE(?label), LCASE(?searchString)) ." + + "}" + + "?term ?inVocabulary ?vocabulary ." + + "} ORDER BY " + orderSentence( config.getLanguage(), "?label"), TermDto.class) .setParameter("type", typeUri) + .setParameter("context", context(vocabulary)) .setParameter("hasLabel", LABEL_PROP) .setParameter("inVocabulary", URI.create( cz.cvut.kbss.termit.util.Vocabulary.s_p_je_pojmem_ze_slovniku)) @@ -605,14 +618,13 @@ public List findAll(String searchString, Vocabulary vocabulary) { public List findAll(String searchString) { Objects.requireNonNull(searchString); final TypedQuery query = em.createNativeQuery("SELECT DISTINCT ?term WHERE {" + - "GRAPH ?vocabulary { " + - "?term a ?type ; " + - " ?hasLabel ?label ; " + - "FILTER CONTAINS(LCASE(?label), LCASE(?searchString)) ." + - "}" + - "?term ?inVocabulary ?vocabulary . " + - "FILTER NOT EXISTS {?term a ?snapshot . }" + - "} ORDER BY " + orderSentence( + "" + + "?term a ?type ; " + + " ?hasLabel ?label ; " + + "FILTER CONTAINS(LCASE(?label), LCASE(?searchString)) ." + + "?term ?inVocabulary ?vocabulary . " + + "FILTER NOT EXISTS {?term a ?snapshot . }" + + "} ORDER BY " + orderSentence( config.getLanguage(), "?label"), TermDto.class) .setParameter("type", typeUri) .setParameter("hasLabel", LABEL_PROP) @@ -651,20 +663,20 @@ public List findAllIncludingImported(String searchString, Vocabulary vo Objects.requireNonNull(searchString); Objects.requireNonNull(vocabulary); final TypedQuery query = em.createNativeQuery("SELECT DISTINCT ?term WHERE {" + - "?targetVocabulary ?imports* ?vocabulary ." + - "?term a ?type ;\n" + - " ?hasLabel ?label ;\n" + - " ?inVocabulary ?vocabulary ." + - "FILTER CONTAINS(LCASE(?label), LCASE(?searchString)) .\n" + - "} ORDER BY " + orderSentence( + "?targetVocabulary ?imports* ?vocabulary ." + + "?term a ?type ;\n" + + " ?hasLabel ?label ;\n" + + " ?inVocabulary ?vocabulary ." + + "FILTER CONTAINS(LCASE(?label), LCASE(?searchString)) .\n" + + "} ORDER BY " + orderSentence( config.getLanguage(), "?label"), TermDto.class) .setParameter("type", typeUri) .setParameter("hasLabel", LABEL_PROP) .setParameter("inVocabulary", URI.create( cz.cvut.kbss.termit.util.Vocabulary.s_p_je_pojmem_ze_slovniku)) .setParameter("imports", - URI.create( - cz.cvut.kbss.termit.util.Vocabulary.s_p_importuje_slovnik)) + URI.create( + cz.cvut.kbss.termit.util.Vocabulary.s_p_importuje_slovnik)) .setParameter("targetVocabulary", vocabulary.getUri()) .setParameter("searchString", searchString, config.getLanguage()); try { @@ -691,17 +703,17 @@ public boolean existsInVocabulary(String label, Vocabulary vocabulary, String la Objects.requireNonNull(vocabulary); try { return em.createNativeQuery("ASK { ?term a ?type ; " + - "?hasLabel ?label ;" + - "?inVocabulary ?vocabulary ." + - "FILTER (LCASE(?label) = LCASE(?searchString)) . " - + "}", Boolean.class) + "?hasLabel ?label ;" + + "?inVocabulary ?vocabulary ." + + "FILTER (LCASE(?label) = LCASE(?searchString)) . " + + "}", Boolean.class) .setParameter("type", typeUri) .setParameter("hasLabel", LABEL_PROP) .setParameter("inVocabulary", - URI.create(cz.cvut.kbss.termit.util.Vocabulary.s_p_je_pojmem_ze_slovniku)) + URI.create(cz.cvut.kbss.termit.util.Vocabulary.s_p_je_pojmem_ze_slovniku)) .setParameter("vocabulary", vocabulary) .setParameter("searchString", label, - languageTag != null ? languageTag : config.getLanguage()).getSingleResult(); + languageTag != null ? languageTag : config.getLanguage()).getSingleResult(); } catch (RuntimeException e) { throw new PersistenceException(e); } @@ -715,15 +727,15 @@ public boolean existsInVocabulary(String label, Vocabulary vocabulary, String la */ public List findAllUnused(Vocabulary vocabulary) { return em.createNativeQuery("SELECT DISTINCT ?term WHERE { " - + " ?term ?inVocabulary ?vocabulary . " - + " FILTER NOT EXISTS {?x ?hasTerm ?term ; " - + " ?hasTarget/?hasSource ?resource.}" - + "}", - URI.class) + + " ?term ?inVocabulary ?vocabulary . " + + " FILTER NOT EXISTS {?x ?hasTerm ?term ; " + + " ?hasTarget/?hasSource ?resource.}" + + "}", + URI.class) .setParameter("vocabulary", vocabulary.getUri()) .setParameter("inVocabulary", - URI.create( - cz.cvut.kbss.termit.util.Vocabulary.s_p_je_pojmem_ze_slovniku)) + URI.create( + cz.cvut.kbss.termit.util.Vocabulary.s_p_je_pojmem_ze_slovniku)) .setParameter("hasTerm", URI.create(cz.cvut.kbss.termit.util.Vocabulary.s_p_je_prirazenim_termu)) .setParameter("hasTarget", URI.create(cz.cvut.kbss.termit.util.Vocabulary.s_p_ma_cil)) .setParameter("hasSource", URI.create(cz.cvut.kbss.termit.util.Vocabulary.s_p_ma_zdroj)) diff --git a/src/main/java/cz/cvut/kbss/termit/persistence/snapshot/CascadingSnapshotCreator.java b/src/main/java/cz/cvut/kbss/termit/persistence/snapshot/CascadingSnapshotCreator.java index 233a905bd..c70e4b6b1 100644 --- a/src/main/java/cz/cvut/kbss/termit/persistence/snapshot/CascadingSnapshotCreator.java +++ b/src/main/java/cz/cvut/kbss/termit/persistence/snapshot/CascadingSnapshotCreator.java @@ -93,7 +93,7 @@ private List resolveVocabulariesToSnapshot(Vocabulary root) { .setParameter("vocabulary", toSnapshot.get(i)) .setParameter("cascadingRelationships", CASCADE_RELATIONSHIPS) .getResultList()); - // Explicitly imported vocabularies (it is likely it they were already added due to term relationships, but just + // Explicitly imported vocabularies (it is likely they were already added due to term relationships, but just // to be sure) toAdd.addAll(em.createNativeQuery("SELECT DISTINCT ?imported WHERE { ?v ?imports ?imported . }", URI.class) .setParameter("imports", URI.create(cz.cvut.kbss.termit.util.Vocabulary.s_p_importuje_slovnik)) diff --git a/src/main/resources/query/snapshot/term.ru b/src/main/resources/query/snapshot/term.ru index 011ed2fb7..458602217 100644 --- a/src/main/resources/query/snapshot/term.ru +++ b/src/main/resources/query/snapshot/term.ru @@ -15,9 +15,10 @@ INSERT { ?y ?z . } } WHERE { - GRAPH ?vocabulary { + GRAPH ?context { ?t a skos:Concept ; skos:inScheme ?glossary ; + pdp:je-pojmem-ze-slovníku ?vocabulary ; ?y ?z . OPTIONAL { ?t skos:broader ?broader . diff --git a/src/main/resources/query/snapshot/vocabulary.ru b/src/main/resources/query/snapshot/vocabulary.ru index 9e76b1b08..03d2a00e0 100644 --- a/src/main/resources/query/snapshot/vocabulary.ru +++ b/src/main/resources/query/snapshot/vocabulary.ru @@ -23,7 +23,7 @@ INSERT { pdp:má-datum-a-čas-vytvoření-verze ?created . } } WHERE { - GRAPH ?vocabulary { + GRAPH ?context { ?vocabulary a pdp:slovník ; pdp:má-glosář ?glossary ; pdp:má-model ?model ;