jabref icon indicating copy to clipboard operation
jabref copied to clipboard

Generic way to store preferences in .bib file

Open ColinScarato opened this issue 2 years ago • 16 comments

Jabref allows to store part of its settings in a database-specific way directly in a given .bib file: https://docs.jabref.org/setup/databaseproperties

I would find super useful to be able to store more of these settings in a .bib file (use case: a big group of collaborators working on a database under version control, with a lot of settings that we currently need to maintain for every collaborator separately). Given that there is already a mechanism to export/import these preferences with an .xml file, could it be possible to implement this in a similar way for .bib files, in order to automatically load all of these preferences if present when opening a given database? Or does Jabref only support globally setting some of these values?

In particular I would need the following settings:

  • mainTableColumnNames
  • mainTableColumnSortTypes
  • mainTableColumnSortOrder
  • customTabName_0
  • customTabFields_0
  • useOwner
  • addCreationDate
  • reformatFileOnSaveAndExport
  • useRemoteServer
  • bibLocAsPrimaryDir
  • customizedBibtexTypes

Thanks!

ColinScarato avatar Apr 20 '22 15:04 ColinScarato

Hi, I am a new contributor to and I would like to make an attempt at resolving this issue. Could it please be assigned to me?

I have followed the instructions and set up a local workspace.

I have also read the contribution guide.

I was hoping I could receive some advice/pointers on where to begin with this issue.

yanyanliu1400 avatar Oct 16 '22 23:10 yanyanliu1400

Marking this with devcall to explore the idea of storing more preferences in the bib file.

Related issue: #8836

What speaks for this:

  • Eases maintaining of shared databases

What speaks against:

  • Bib file pollution (When it is NOT wanted to automatically load preferences from colleagues in a shared database)
  • Most (but not all) JabRef preferences are stored elsewhere (might lead to confusion)

@yanyanliu1400 this is a tough issue that requires a lot of thinking so as to not create problems for many people that are not in need of these specific preferences. Since this is your first contribution to JabRef, please have a look at our projects page with "good first issues". If you are a student, the "candidates for university projects" page offers some issues of varying difficulty and scope and that have been estimated to be compatible with university courses as well and often bring a larger feature to JabRef. I think you already found another issue to work on though.

ThiloteE avatar Oct 17 '22 10:10 ThiloteE

Workaround

Alternatively, one could export the JabRef preferences and have all users importing the database.

Local Library Settings (Solution with one file)

  • useOwner grafik
  • addCreationDate grafik
  • reformatFileOnSaveAndExport
  • useRemoteServer --> This is already possible when a bib file is synchronized with a local file - https://docs.jabref.org/collaborative-work/sqldatabase. Maybe, it does not work as expected when the bib file is opened by a user not having connected to the database yet grafik
  • bibLocAsPrimaryDir --> This is not required because one can set "." as main file directory grafik
  • customizedBibtexTypes - Documentation: https://docs.jabref.org/setup/customentrytypes - currently, JabRef stores the used entry types
  • Linked File Name
    • grafik
    • grafik
  • mainTableColumnNames
  • mainTableColumnSortTypes
  • mainTableColumnSortOrder
  • customTabName_0
  • customTabFields_0

UI: Each check tri-state: selected, unslected, grayed-out. If grayed-out, the global setting is used and the grayed-out box should be in the state of the global configuration.

Note: This approach is simlar to the file directory setting approach of JabRef:

grafik

Solution with multiple files (workspace concept)

JabRef could introduce the concept of a workspace, where multiple files are included. When sharing, the complete folder could be shared. The folder could contain

  • Shared preferences
  • Related references (see https://github.com/JabRef/jabref/pull/7160#issuecomment-757556724)

Similar to IntelliJ's global preferences and module-/project-specific preferences.

(not chosen) Solution with exported preferences handled by JabRef

Filename is papers.bib. There could be a file papers.jabref-preferences.xml. If JabRef finds that file, it loads these preferences when the library is focused. If it is unfocused, then the "old" preferences are restored.

Alternative: In the meta data, the path to the preferences can be configured.

  1. grafik --> preferences of "test541.bib" are loaded
  2. grafik --> global preferences are used
  • Bad, because performance could go low (because of the abbreviations)
  • Bad, because possibly non-understandable by users

koppor avatar Oct 24 '22 20:10 koppor

If tackling this issue, each setting has to be investigated separately:

  • Locate the settings component in our property dialog code and make that component resuable (see the Key Patterns component as example) grafik
    grafik
  • Include the setting in the library properties
  • Have the preference resolution ask the library setting and then the global setting
  • Adapt initialization of setting

koppor avatar Oct 24 '22 20:10 koppor

Hi I'm a university student with an assignment to contribute to an open source repository, would this be a good issue for me to work on?

taliashark77 avatar Oct 16 '23 01:10 taliashark77

@taliashark77 at the right top side of github you see the projects page. While this is marked as good first issue, I assume it was more because this project can be seen as a good first entry into our code base.

This is a medium sized project, as you can see here: image

Since this would be your first ever pull-request on GitHub, I assume you are very new to coding and therefore, I suggest to check out our good first issues projects page or alternatively choose one of the small projects. I recommend this issue to students with a little bit more experience. E.g. non-first semesters or somebody who has started to code before joining university.

ThiloteE avatar Oct 16 '23 07:10 ThiloteE

@ThiloteE Thanks for your response, I will try look for some more beginner friendly issues

taliashark77 avatar Oct 16 '23 08:10 taliashark77

Hi All. I have posted a similar request here:

https://discourse.jabref.org/t/different-entry-table-views/4125/3

For now, I have done something completely insane. Which is to created a separate preferences file for each bib file and then created a launcher for each that loads the respective bib file along with the corresponding preferences with the appropriate arguments.

Just a thought of the top of my head... Perhaps something simpler could be done regarding the order of how the preferences are checked. That is maybe before checking the system configs seeing if there is a preferences file that matches the name of the bib file in a specified folder. So, if it does not exist, jabref is launched with the preferences that are stared at the java level (or wherever it is on the system). If there is a file match, then those preference are loaded.

mwinter80 avatar Jan 09 '24 22:01 mwinter80

seeing if there is a preferences file that matches the name of the bib file in a specified folder.

Maybe, that file could even be stored along side the .bib file? Then it would also be sharable using git or OneDrive.

koppor avatar Jan 09 '24 23:01 koppor

seeing if there is a preferences file that matches the name of the bib file in a specified folder.

Maybe, that file could even be stored along side the .bib file? Then it would also be sharable using git or OneDrive.

seems reasonable and simple : )

mwinter80 avatar Jan 09 '24 23:01 mwinter80

Code hint for the "straight-forward" along-side storage:

  • org.jabref.preferences.JabRefPreferences#flush

This comment will updated with other code hints as soon as I stumple on them.

koppor avatar Jan 11 '24 11:01 koppor

It has been a while since I have been in Java-land, but I could help here. I looked at the code around line 497 would be where the check happens as there is already one there. The tricker part will be how to deal with the hook such that there is a check based on the bib file that is being opened.

mwinter80 avatar Jan 11 '24 11:01 mwinter80

Fortunately, we have a step-by-step-guide to setup a local workspace: https://devdocs.jabref.org/getting-into-the-code/guidelines-for-setting-up-a-local-workspace/#setup-for-eclipse 🤣🤣

General thoughts:

  • JabRef can have multiple opened libraries. One library can have library-specific preferences, one not.
  • We do not want to rewrite the whole preference logic, the "hack" with the portable preferences seems to have less code
  • We want to have the "magic" being enabled only if there is one library opened with library-specific preferences.

Consequences:

  • Thus, we need global-profs.xml. Can be stored in AppData\Local\org.jabref\jabref\settings. New method analogues to org.jabref.gui.desktop.os.NativeDesktop#getBackupDirectory needed.
  • Global flag libararySpecificSettingsInPlace. Default: false. Held in org.jabref.gui.StateManager
  • On focus a library hook into
    • org.jabref.gui.LibraryTab#LibraryTab --> add setOnSelectionChanged
  • hook:
    • on focus lost: store old preferences (if available)
    • on focus gained: load new preferences
  • hook into closed library (maybe not necessary, because of other hook, I am not sure about the live cycle)
    • store old preferences
  • store old preferences: only required if local settings are available
  • load new preferences: only if local settings are available
  • in bibdatabasecontext.getmetadata, it should be stored if local should be used. (boolean)

(Have to leave now, with the metadata, i am not sure how to full. Maybe quick hack: return files.exists(...xml) so that the property is magically filled)

koppor avatar Jan 11 '24 13:01 koppor

Ok! Very insightful. It might take me a bit to get up and running. I will keep you posted...

mwinter80 avatar Jan 12 '24 02:01 mwinter80

Just a note for a technical motivation for the issue - not related to the currently proposed first-solution. This is more a comment for the long run.

    @BeforeEach
    public void setUp() {
        importer = new BibtexImporter(mock(ImportFormatPreferences.class, Answers.RETURNS_DEEP_STUBS), new DummyFileUpdateMonitor());

        stringWriter = new StringWriter();
        bibWriter = new BibWriter(stringWriter, OS.NEWLINE);
        saveConfiguration = new SelfContainedSaveConfiguration(SaveOrder.getDefaultSaveOrder(), false, BibDatabaseWriter.SaveType.WITH_JABREF_META_DATA, false);
        fieldPreferences = new FieldPreferences(true, Collections.emptyList(), Collections.emptyList());
        citationKeyPatternPreferences = mock(CitationKeyPatternPreferences.class, Answers.RETURNS_DEEP_STUBS);
        entryTypesManager = new BibEntryTypesManager();

        databaseWriter = new BibtexDatabaseWriter(
                bibWriter,
                saveConfiguration,
                fieldPreferences,
                citationKeyPatternPreferences,
                entryTypesManager);
    }

    @Test
    void anonymizeLibrary() throws Exception {
        Path path = Path.of("C:\\temp\\P4\\biblio.bib");
        BibDatabaseContext databaseContext = importer.importDatabase(path).getDatabaseContext();

        Anonymization anonymization = new Anonymization();
        BibDatabaseContext result = anonymization.anonymizeLibrary(databaseContext);

        databaseWriter.saveDatabase(databaseContext);

        Files.writeString(Path.of("C:\\temp\\P4\\biblio-anon.bib"), stringWriter.toString());

        assertEquals(null, result);
    }

In the long run, a simple read and write of a library should use defaults - and not require some library-external preferences.

koppor avatar Jan 12 '24 23:01 koppor

First step: Support keywords per library:

image

Then, one learns about the consequences and can cover the other preferences step-by-step. With "learn", I mean: the right architecture, the necessary code changes, ... Maybe, we even need a generic preferencesFactory being initialized with the BibDatabaseContext and the JabRefPreferenceService - and then first checks the context. If not set, then it checks the global preferences. I think, this is the most stramlined way.

Especially, following code in GrammarBasedSearchRule needs to be updated

            if (fieldPattern.matcher("anykeyword").matches()) {
                return entry.getKeywords(',').stream().map(Keyword::toString).anyMatch(this::matchFieldValue);
            }

koppor avatar Mar 03 '24 13:03 koppor