Skip to content
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

[Enhancement kbss-cvut/termit-ui#520] Change record filtering #313

Merged
merged 21 commits into from
Nov 25, 2024
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
1486e9f
[Enhancement kbss-cvut/termit-ui#520] Update vocabulary content histo…
lukaskabc Nov 1, 2024
39422e5
[Enhancement kbss-cvut/termit-ui#520] Fix Vocabulary content changes …
lukaskabc Nov 4, 2024
426c9c4
[Enhancement kbss-cvut/termit-ui#520] Add tests for delete records an…
lukaskabc Nov 5, 2024
154b8aa
[Enhancement kbss-cvut/termit-ui#520] Add tests for change record fil…
lukaskabc Nov 5, 2024
08aa466
[Enhancement kbss-cvut/termit-ui#520] Add parametrized test for filte…
lukaskabc Nov 6, 2024
7e61939
[Enhancement kbss-cvut/termit-ui#520] Test that detailed history of v…
lukaskabc Nov 10, 2024
34b7bbb
[Ref] Optimize imports
lukaskabc Nov 10, 2024
eee60a9
[Enhancement kbss-cvut/termit-ui#520] Move change record implementati…
lukaskabc Nov 10, 2024
54b819e
[Enhancement kbss-cvut/termit-ui#520] Add filtering options for vocab…
lukaskabc Nov 10, 2024
8a1dcc9
[Enhancement kbss-cvut/termit-ui#520] Fix tests after rebase
lukaskabc Nov 11, 2024
4334617
[Enhancement kbss-cvut/termit-ui#520] Fix change record filter query
lukaskabc Nov 13, 2024
edfbbe5
[Enhancement kbss-cvut/termit-ui#520] Fix change record filter query
lukaskabc Nov 14, 2024
ca0af58
[Enhancement kbss-cvut/termit-ui#528] Change TermDao#resolveVocabular…
lukaskabc Nov 14, 2024
6c5797b
[Enhancement kbss-cvut/termit-ui#520] Move ChangeRecordDao tests from…
lukaskabc Nov 14, 2024
e572355
[Enhancement kbss-cvut/termit-ui#520] Fix tests not saving change rec…
lukaskabc Nov 14, 2024
a657a98
[Enhancement kbss-cvut/termit-ui#520] Refactor ChangeRecordDao public…
lukaskabc Nov 14, 2024
9c04678
[Enhancement kbss-cvut/termit-ui#520] ChangeRecordDaoTest cleanup
lukaskabc Nov 14, 2024
de1e76a
[Ref] Cleanup changes for PR
lukaskabc Nov 15, 2024
58302d9
[Enhancement kbss-cvut/termit-ui#520] Use constants for api descripti…
lukaskabc Nov 24, 2024
ab07485
[Enhancement kbss-cvut/termit-ui#520] Replace System#currentTimeMilli…
lukaskabc Nov 24, 2024
ffad638
Merge branch 'development' into lukaskabc/Enhancement-520
lukaskabc Nov 24, 2024
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package cz.cvut.kbss.termit.dto.filter;

import com.fasterxml.jackson.annotation.JsonIgnore;
import cz.cvut.kbss.termit.util.Utils;

import java.net.URI;
import java.util.Objects;

/**
* Represents parameters for filtering vocabulary content changes.
*/
public class ChangeRecordFilterDto {
private String assetLabel = "";
private String changedAttributeName = "";
private String authorName = "";
private URI changeType = null;

public String getAssetLabel() {
return assetLabel;
}

public void setAssetLabel(String assetLabel) {
this.assetLabel = assetLabel;
}

public String getChangedAttributeName() {
return changedAttributeName;
}

public void setChangedAttributeName(String changedAttributeName) {
this.changedAttributeName = changedAttributeName;
}

public String getAuthorName() {
return authorName;
}

public void setAuthorName(String authorName) {
this.authorName = authorName;
}

public URI getChangeType() {
return changeType;
}

public void setChangeType(URI changeType) {
this.changeType = changeType;
}

/**
* @return true when all attributes are empty or null
*/
@JsonIgnore
public boolean isEmpty() {
return Utils.isBlank(assetLabel) &&
Utils.isBlank(changedAttributeName) &&
Utils.isBlank(authorName) &&
changeType == null;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ChangeRecordFilterDto that)) return false;
return Objects.equals(assetLabel, that.assetLabel) &&
Objects.equals(changedAttributeName, that.changedAttributeName) &&
Objects.equals(authorName, that.authorName) &&
Objects.equals(changeType, that.changeType);
}

@Override
public int hashCode() {
return Objects.hash(assetLabel, changedAttributeName, authorName, changeType);
}


/**
* Constants for the Open API documentation of the REST API.
*/
public static final class ApiDoc {
public static final String TERM_NAME_DESCRIPTION = "Name of the term used for filtering.";
public static final String CHANGE_TYPE_DESCRIPTION = "Type of the change used for filtering.";
public static final String AUTHOR_NAME_DESCRIPTION = "Name of the author of the change used for filtering.";
public static final String CHANGED_ATTRIBUTE_DESCRIPTION = "Name of the changed attribute used for filtering.";

private ApiDoc() {
throw new AssertionError();
}
}
}
12 changes: 6 additions & 6 deletions src/main/java/cz/cvut/kbss/termit/persistence/dao/TermDao.java
Original file line number Diff line number Diff line change
Expand Up @@ -91,23 +91,23 @@ protected URI labelProperty() {
@Override
public Optional<Term> find(URI id) {
try {
final Optional<Term> result = Optional.ofNullable(
em.find(Term.class, id, descriptorFactory.termDescriptor(resolveVocabularyId(id))));
final Optional<Term> result = resolveVocabularyId(id).map(vocabulary ->
em.find(Term.class, id, descriptorFactory.termDescriptor(vocabulary)));
result.ifPresent(this::postLoad);
return result;
} catch (RuntimeException e) {
throw new PersistenceException(e);
}
}

private URI resolveVocabularyId(URI termId) {
private Optional<URI> resolveVocabularyId(URI termId) {
try {
return em.createNativeQuery("SELECT DISTINCT ?v WHERE { ?t ?inVocabulary ?v . }", URI.class)
return Optional.of(em.createNativeQuery("SELECT DISTINCT ?v WHERE { ?t ?inVocabulary ?v . }", URI.class)
.setParameter("t", termId)
.setParameter("inVocabulary", TERM_FROM_VOCABULARY)
.getSingleResult();
.getSingleResult());
} catch (NoResultException | NoUniqueResultException e) {
throw new PersistenceException("Unable to resolve term vocabulary.", e);
return Optional.empty();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

import cz.cvut.kbss.jopa.model.EntityManager;
import cz.cvut.kbss.jopa.model.query.Query;
import cz.cvut.kbss.jopa.model.query.TypedQuery;
import cz.cvut.kbss.jopa.vocabulary.DC;
import cz.cvut.kbss.jopa.vocabulary.SKOS;
import cz.cvut.kbss.termit.asset.provenance.ModifiesData;
Expand All @@ -28,6 +27,7 @@
import cz.cvut.kbss.termit.dto.PrefixDeclaration;
import cz.cvut.kbss.termit.dto.RdfsStatement;
import cz.cvut.kbss.termit.dto.Snapshot;
import cz.cvut.kbss.termit.dto.filter.ChangeRecordFilterDto;
import cz.cvut.kbss.termit.event.AssetPersistEvent;
import cz.cvut.kbss.termit.event.AssetUpdateEvent;
import cz.cvut.kbss.termit.event.BeforeAssetDeleteEvent;
Expand All @@ -43,6 +43,7 @@
import cz.cvut.kbss.termit.model.validation.ValidationResult;
import cz.cvut.kbss.termit.persistence.context.DescriptorFactory;
import cz.cvut.kbss.termit.persistence.context.VocabularyContextMapper;
import cz.cvut.kbss.termit.persistence.dao.changetracking.ChangeRecordDao;
import cz.cvut.kbss.termit.persistence.snapshot.AssetSnapshotLoader;
import cz.cvut.kbss.termit.persistence.validation.VocabularyContentValidator;
import cz.cvut.kbss.termit.service.snapshot.SnapshotProvider;
Expand Down Expand Up @@ -88,6 +89,7 @@ public class VocabularyDao extends BaseAssetDao<Vocabulary>
"} GROUP BY ?date HAVING (?cnt > 0) ORDER BY ?date";

private static final String REMOVE_GLOSSARY_TERMS_QUERY_FILE = "remove/removeGlossaryTerms.ru";
private final ChangeRecordDao changeRecordDao;

private volatile long lastModified;

Expand All @@ -97,11 +99,13 @@ public class VocabularyDao extends BaseAssetDao<Vocabulary>

@Autowired
public VocabularyDao(EntityManager em, Configuration config, DescriptorFactory descriptorFactory,
VocabularyContextMapper contextMapper, ApplicationContext context) {
VocabularyContextMapper contextMapper, ApplicationContext context,
ChangeRecordDao changeRecordDao) {
super(Vocabulary.class, em, config.getPersistence(), descriptorFactory);
this.contextMapper = contextMapper;
refreshLastModified();
this.context = context;
this.changeRecordDao = changeRecordDao;
}

@Override
Expand Down Expand Up @@ -402,32 +406,9 @@ public List<AggregatedChangeInfo> getChangesOfContent(Vocabulary vocabulary) {
* @param pageReq Specification of the size and number of the page to return
* @return List of change records, ordered by date in descending order
*/
public List<AbstractChangeRecord> getDetailedHistoryOfContent(Vocabulary vocabulary, Pageable pageReq) {
public List<AbstractChangeRecord> getDetailedHistoryOfContent(Vocabulary vocabulary, ChangeRecordFilterDto filter, Pageable pageReq) {
Objects.requireNonNull(vocabulary);
return createDetailedContentChangesQuery(vocabulary, pageReq).getResultList();
}

private TypedQuery<AbstractChangeRecord> createDetailedContentChangesQuery(Vocabulary vocabulary, Pageable pageReq) {
return em.createNativeQuery("""
SELECT ?record WHERE {
?term ?inVocabulary ?vocabulary ;
a ?termType .
?record a ?changeRecord ;
?relatesTo ?term ;
?hasTime ?timestamp .
OPTIONAL { ?record ?hasChangedAttribute ?attribute . }
} ORDER BY DESC(?timestamp) ?attribute
""", AbstractChangeRecord.class)
.setParameter("inVocabulary",
URI.create(cz.cvut.kbss.termit.util.Vocabulary.s_p_je_pojmem_ze_slovniku))
.setParameter("vocabulary", vocabulary)
.setParameter("termType", URI.create(SKOS.CONCEPT))
.setParameter("changeRecord", URI.create(cz.cvut.kbss.termit.util.Vocabulary.s_c_zmena))
.setParameter("relatesTo", URI.create(cz.cvut.kbss.termit.util.Vocabulary.s_p_ma_zmenenou_entitu))
.setParameter("hasTime", URI.create(cz.cvut.kbss.termit.util.Vocabulary.s_p_ma_datum_a_cas_modifikace))
.setParameter("hasChangedAttribute", URI.create(cz.cvut.kbss.termit.util.Vocabulary.s_p_ma_zmeneny_atribut))
.setFirstResult((int) pageReq.getOffset())
.setMaxResults(pageReq.getPageSize());
return changeRecordDao.findAllRelatedToType(vocabulary, filter, URI.create(SKOS.CONCEPT), pageReq);
}

private Query createContentChangesQuery(Vocabulary vocabulary) {
Expand Down
Loading