-
-
Notifications
You must be signed in to change notification settings - Fork 3k
New study.yml format #13844
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
base: main
Are you sure you want to change the base?
New study.yml format #13844
Conversation
…ns from the current study.yml version to the new one
…n and parsing of study.yml if needed
…r to avoid deadlock
…igrator to JSpecify annotations
…nstead of StudyYamlParser
…ith the rest of the codebase
… from getCatalogSpecific form StudyQuery
@@ -8,7 +8,7 @@ | |||
import org.jabref.logic.importer.ImportFormatPreferences; | |||
import org.jabref.logic.importer.ImporterPreferences; | |||
import org.jabref.model.study.Study; | |||
import org.jabref.model.study.StudyDatabase; | |||
import org.jabref.model.study.StudyCatalog; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The import statement for StudyCatalog is correct, but the patch does not address the need to use JavaFX ObservableLists for better practice in managing lists in JavaFX applications.
@@ -92,14 +92,14 @@ void studyConstructorFillsDatabasesCorrectly(@TempDir Path tempDir) { | |||
} | |||
|
|||
private ManageStudyDefinitionViewModel getManageStudyDefinitionViewModel(Path tempDir) { | |||
List<StudyDatabase> databases = List.of( | |||
new StudyDatabase("ACM Portal", true)); | |||
List<StudyCatalog> catalogs = List.of( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code uses List.of() which is correct, but it does not utilize JavaFX ObservableLists, which is considered best practice for managing lists in JavaFX applications.
StudyYamlParser studyYAMLParser = new StudyYamlParser(); | ||
studyYAMLParser.writeStudyYamlFile(newStudy, studyRepositoryRoot.resolve(StudyRepository.STUDY_DEFINITION_FILE_NAME)); | ||
StudyYamlService studyYamlService = new StudyYamlService(); | ||
studyYamlService.writeStudyYamlFile(newStudy, studyRepositoryRoot.resolve(StudyRepository.STUDY_DEFINITION_FILE_NAME)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method writeStudyYamlFile should ensure it does not return null. If it does, it should use java.util.Optional to handle potential null values.
jablib/src/main/java/org/jabref/logic/crawler/StudyYamlV1Migrator.java
Outdated
Show resolved
Hide resolved
|
||
if (CURRENT_VERSION.equals(version)) { | ||
// Already current version, read the file normally | ||
try (InputStream fileInputStream = Files.newInputStream(studyYamlFile)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The try block covers the entire method, which is against best practices. It should cover as few statements as possible to minimize the scope of potential exceptions.
} | ||
|
||
@JsonSetter("metadata") | ||
public void setMetadata(Optional<StudyMetadata> metadata) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method setMetadata should not accept null values. Consider using Optional.ofNullable to handle potential null inputs gracefully.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Passing Optionals as Arguments is rarely a good, especially if the nextline reads if the optional itself is checked for null in the next line. This seems not intended. Use Optionals as return types, not as fields or arguments.
Study study; | ||
try { | ||
study = new StudyYamlParser().parseStudyYamlFile(studyDirectory.resolve(StudyRepository.STUDY_DEFINITION_FILE_NAME)); | ||
study = new StudyYamlService().parseStudyYamlFile(studyDirectory.resolve(StudyRepository.STUDY_DEFINITION_FILE_NAME)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The try block covers too many statements, which is against best practices. It should only cover the statement that might throw the exception to improve readability and maintainability.
private Optional<String> getVersionFromFile(Path studyYamlFile) throws IOException { | ||
ObjectMapper yamlMapper = new ObjectMapper(new YAMLFactory()); | ||
|
||
try (InputStream fileInputStream = Files.newInputStream(studyYamlFile)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The try block covers multiple statements, which is not recommended. It should cover as few statements as possible to isolate potential exceptions.
*/ | ||
public Study parseStudyYamlFile(Path studyYamlFile) throws IOException { | ||
if (needsMigration(studyYamlFile)) { | ||
Study migratedStudy = StudyYamlMigrator.migrateStudyYamlFile(studyYamlFile); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method migrateStudyYamlFile should not return null. It should return an Optional or throw an exception if migration fails.
@Test | ||
void parseStudyFileSuccessfully() throws IOException { | ||
Study study = new StudyYamlParser().parseStudyYamlFile(testDirectory.resolve(StudyRepository.STUDY_DEFINITION_FILE_NAME)); | ||
Study study = new StudyYamlService().parseStudyYamlFile(testDirectory.resolve(StudyRepository.STUDY_DEFINITION_FILE_NAME)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method parseStudyYamlFile should throw a generic Exception instead of IOException to adhere to the instruction of using 'throws Exception' in the method declaration.
URL studyDefinition = StudyYamlParser.class.getResource("study-jabref-5.7.yml"); | ||
Study study = new StudyYamlParser().parseStudyYamlFile(Path.of(studyDefinition.toURI())); | ||
URL studyDefinition = StudyYamlService.class.getResource("study-jabref-5.7.yml"); | ||
Study study = new StudyYamlService().parseStudyYamlFile(Path.of(studyDefinition.toURI())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method parseStudyYamlFile should throw a generic Exception instead of IOException to adhere to the instruction of using 'throws Exception' in the method declaration.
/** | ||
* Creates metadata by extracting information from file and existing data | ||
*/ | ||
private StudyMetadata createMetadata(Path studyYamlFile, V1StudyFormat oldStudy) throws IOException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Likewise here: Annotate with @NonNull
} else if (queryObj instanceof Map) { | ||
@SuppressWarnings("unchecked") | ||
Map<String, Object> queryMap = (Map<String, Object>) queryObj; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
} else if (queryObj instanceof Map) { | |
@SuppressWarnings("unchecked") | |
Map<String, Object> queryMap = (Map<String, Object>) queryObj; | |
} else if (queryObj instanceof Map<String, Object> queryMap) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if this works with SuppressWarnings
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This gives a unsafe casting error though
…tor.java Co-authored-by: Carl Christian Snethlage <[email protected]>
* Generate notes for the migration | ||
*/ | ||
private String generateMigrationNotes(V1StudyFormat oldStudy) { | ||
StringJoiner notes = new StringJoiner(" "); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
StringJoiner is used correctly here, but ensure that it is used consistently throughout the codebase for string concatenation to maintain consistency.
@trag-bot didn't find any issues in the code! ✅✨ |
assertEquals(expectedStudy, study); | ||
} | ||
|
||
@Test | ||
void writeStudyFileSuccessfully() throws IOException { | ||
new StudyYamlParser().writeStudyYamlFile(expectedStudy, testDirectory.resolve(StudyRepository.STUDY_DEFINITION_FILE_NAME)); | ||
Study study = new StudyYamlParser().parseStudyYamlFile(testDirectory.resolve(StudyRepository.STUDY_DEFINITION_FILE_NAME)); | ||
new StudyYamlService().writeStudyYamlFile(expectedStudy, testDirectory.resolve(StudyRepository.STUDY_DEFINITION_FILE_NAME)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method writeStudyYamlFile should throw a generic Exception instead of IOException to adhere to the principle of letting JUnit handle exceptions in tests.
@@ -58,8 +58,8 @@ void readsJabRef57StudySuccessfully() throws URISyntaxException, IOException { | |||
// If the field is "just" removed from the datamodel, one gets following exception: | |||
// com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "last-search-date" (class org.jabref.model.study.Study), not marked as ignorable (5 known properties: "authors", "research-questions", "queries", "title", "databases"]) | |||
// This tests ensures that this exception does not occur | |||
URL studyDefinition = StudyYamlParser.class.getResource("study-jabref-5.7.yml"); | |||
Study study = new StudyYamlParser().parseStudyYamlFile(Path.of(studyDefinition.toURI())); | |||
URL studyDefinition = StudyYamlService.class.getResource("study-jabref-5.7.yml"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method readsJabRef57StudySuccessfully should throw a generic Exception instead of IOException and URISyntaxException to adhere to the principle of letting JUnit handle exceptions in tests.
assertEquals("Database2", catalogs.get(1).getName()); | ||
|
||
// Third database explicitly disabled | ||
assertFalse(catalogs.get(2).isEnabled()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code uses assertFalse to check a boolean condition. It should assert the contents of objects using assertEquals for better clarity and precision.
Your code currently does not meet JabRef's code guidelines. We use OpenRewrite to ensure "modern" Java coding practices. You can see which checks are failing by locating the box "Some checks were not successful" on the pull request page. To see the test output, locate "Source Code Tests / OpenRewrite (pull_request)" and click on it. The issues found can be automatically fixed. Please execute the gradle task |
Closes #12642
The study.yml is refactored to a new format to implement SEMVER versioning, variable 'databases' is renamed to 'catalogues' for UI consistency.
In the course of working on this draft pull request the query structure is planned to be enhanced to support multiple query formats including catalog-specific variations.
Steps to test
The study.yml file created when a new slr is started should be in a new format and slr search should function as intended.
New format is:
version: 2.0
authors:
title: title
research-questions:
queries:
description: null
lucene: null
catalogue-specific: null
catalogues:
enabled: true
metadata:
notes: null
created-date: null
last-modified: null
Mandatory checks
CHANGELOG.md
in a way that is understandable for the average user (if change is visible to the user)