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

Add referenced entry's observers to update the entry in the main-table #7754

Open
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

SuXiChangZhen
Copy link
Contributor

@SuXiChangZhen SuXiChangZhen commented May 19, 2021

I change the getField method so that every time it will bind entry and referenced entry(if exists). Although the behavior now seems correct, I don't think it is an appropriate way to solve the problem. Hope for some suggestions.
Mitigates #7730

  • Change in CHANGELOG.md described in a way that is understandable for the average user (if applicable)
  • Tests created for changes (if applicable)
  • Manually tested changed features in running JabRef (always required)
  • Screenshots added in PR description (for UI changes)
  • Checked documentation: Is the information available and up to date? If not created an issue at https://github.com/JabRef/user-documentation/issues or, even better, submitted a pull request to the documentation repository.

ArrayList<Observable> observables = new ArrayList<>(List.of(entry.getObservables()));
Optional<BibEntry> referenced = fieldValueFormatter.getValue().getReferencedEntry(entry);
referenced.ifPresent(bibEntry -> observables.addAll(List.of(bibEntry.getObservables())));
Copy link
Member

@k3KAW8Pnf7mkmdSMPHz27 k3KAW8Pnf7mkmdSMPHz27 May 28, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know enough of JavaFX to tell you for sure how to address this. I'd suggest not removing the caching (fieldValues.get(fields);) and instead deal with the dependencies differently.

  • You can extend StringBinding and use .bind and .unbind to "manually" deal with the dependencies. (this is probably not a good approach)
  • You can extend a different binding (ObjectBinding?) and have it handle changes to the referenced entry. In this scenario, the StringBinding has this ObjectBinding among its dependencies instead of the referenced bibentry's getObservables().
  • At least superficially this seems like a good application for EasyBind because,
    1. You can create an optional binding, e.g., entry.getFieldBinding(StandardField.CROSSREF)
      1. This means you can create an OptionalBinding<BibEntry> referencedBibEntry
    2. It should be possible to keep an observableArrayList with extractor (FXCollections.observableArrayList(BibEntry::getObservables)) updated with the ifValuePresent method of the OptionalBinding<BibEntry> EasyBind.subscribe. That should keep the list up-to-date when the referenced BibEntry is changed/removed and when the observables in the referenced bibEntry.getObservables are modified
    3. This list should now be usable as a dependency

Note that the two last approaches should be used or called from the constructor since they will update on changes to the referenced BibEntry.

I'd appreciate it if someone with more experience of JavaFX chimes in with opinions 😛

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussion:

@artcile{a,
crossref={b}
}

@book{b}

to

@artcile{a,
crossref={c}
}

@book{b}

@book{c}

Changes to c are not reflected accordingly.

Copy link
Member

@koppor koppor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We discussed it in our DevCall and have some comments to move forward here.

Comment on lines 111 to 144
ObservableValue<String> value = fieldValues.get(fields);
if (value != null) {
return value;
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be kept. If it does not work on your side, please comment. This caching helps us to gain performance (in the case of large databases, as this is initialized at the start of JabRef).

We need to update the cache if the referenced crossref entry is changed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Decision: We need to keep this code - and will handle the issue for changed crossref value later (and incorporate the comments of https://github.com/JabRef/jabref/pull/7754/files#r641697015)

ArrayList<Observable> observables = new ArrayList<>(List.of(entry.getObservables()));
Optional<BibEntry> referenced = fieldValueFormatter.getValue().getReferencedEntry(entry);
referenced.ifPresent(bibEntry -> observables.addAll(List.of(bibEntry.getObservables())));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussion:

@artcile{a,
crossref={b}
}

@book{b}

to

@artcile{a,
crossref={c}
}

@book{b}

@book{c}

Changes to c are not reflected accordingly.

@SuXiChangZhen
Copy link
Contributor Author

Thank you for all your comments. In fact, this was my first attempt to solve the issue and it just worked (ugly indeed). The reason I delete the code about the init cache is that if the value is not null, it just return without considering update. So maybe we can consider update the binding in the corresponding places(crossref field is changed, etc.). Currently I still don't figure out a proper way to solve this. So appreciate for your further comments and suggestions! 😊

@k3KAW8Pnf7mkmdSMPHz27
Copy link
Member

@SuXiChangZhen our thinking is that with the caching re-enabled, this is still an improvement on the previous behavior. Perhaps the caching can be re-enabled, you use bibDatabaseContext.getDatabase().getReferencedEntry(entry) and we do a re-review -> merge?

Regarding a "proper way to solve this", unless you have an interest in EasyBind/JavaFX in particular, it is probably not going to be worth your time, it might be better to pick a different issue.

If you want to give it an attempt anyway, we'd still propose fixing the other parts we commented on in this PR, merge, and then create a follow-up PR. I can expand on the suggested approach in #7754 (comment) but I make no guarantees that it will work nor that it is the "proper way" 😛

@Siedlerchr
Copy link
Member

@k3KAW8Pnf7mkmdSMPHz27 Would you mind taking ove the PR so we can finish it? Just add the caching

@k3KAW8Pnf7mkmdSMPHz27 k3KAW8Pnf7mkmdSMPHz27 force-pushed the fix-for-issue-7730 branch 2 times, most recently from 828a066 to 1b50be6 Compare July 22, 2021 21:47
@k3KAW8Pnf7mkmdSMPHz27
Copy link
Member

Ok. I am very sorry for force-pushing to your repository @SuXiChangZhen, definitively last time I am trying that X)
These are the changes we consider sufficient for this PR since it improves on the original JabRef behavior even if it doesn't completely solve the issue.

@Siedlerchr thank you for the git-support X)

@k3KAW8Pnf7mkmdSMPHz27 k3KAW8Pnf7mkmdSMPHz27 changed the title Add referenced entry's observers to update the crossref entry's preview table Add referenced entry's observers to update the entry in the main-table Jul 22, 2021
@k3KAW8Pnf7mkmdSMPHz27
Copy link
Member

k3KAW8Pnf7mkmdSMPHz27 commented Jul 22, 2021

The changes in this PR are the following

  • When an entry was cross-referencing a different entry, changes in (say author) didn't propagate unless JabRef were restarted (or possibly switched back/forth between tabs). Now you'll see the entry being visually updated in real-time when you make changes in the cross-referenced entry.

What remains after this PR,

  • If the entry being cross-referenced is changed, you need to restart/switch tabs again to make the updating work properly again

@calixtus
Copy link
Member

The crossref field is already in the array of the triggers for the CreateStringBinding-method?

@k3KAW8Pnf7mkmdSMPHz27
Copy link
Member

k3KAW8Pnf7mkmdSMPHz27 commented Jul 25, 2021

Yes, but due to the caching, the dependencies on the cross-refs entry’s fields won’t update when cross-ref does (we need to “depend” on all observables in the cross-referenced entry to know when to update, and that is funky to do)

This was why the caching was removed in the original solution.

@calixtus
Copy link
Member

Ah, ok. Rebuilding the cache from an invalidation listener?

@k3KAW8Pnf7mkmdSMPHz27
Copy link
Member

That would probably work. In “theory”, you shouldn't need to rebuild it.

Anyway, that part is why this issue is a bit of a mess. As is, this PR is imo an improvement on the previous behavior without that part as well.

@calixtus
Copy link
Member

We shoudd make a decision here: Merge it, as it is an improvement to the current situation, although it does not solve the issue at all, or try to fix it completly. Putting this on line for next dev call.

# Conflicts:
#	src/main/java/org/jabref/gui/maintable/BibEntryTableViewModel.java
…fix-for-issue-7730

# Conflicts:
#	src/main/java/org/jabref/gui/maintable/BibEntryTableViewModel.java
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your code currently does not meet JabRef's code guidelines.
We use Checkstyle to identify issues.
Please carefully follow the setup guide for the codestyle.
Afterwards, please run checkstyle locally and fix the issues.

In case of issues with the import order, double check that you activated Auto Import.
You can trigger fixing imports by pressing Ctrl+Alt+O to trigger Optimize Imports.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants