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

[WIP] CSL citations: Fix sync numbering #11688

Closed
wants to merge 13 commits into from
16 changes: 9 additions & 7 deletions src/main/java/org/jabref/gui/openoffice/OOBibBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@
import com.sun.star.lang.WrappedTargetException;
import com.sun.star.text.XTextCursor;
import com.sun.star.text.XTextDocument;
import com.sun.star.uno.Exception;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -86,12 +85,12 @@ public OOBibBase(Path loPath, DialogService dialogService)
this.alwaysAddCitedOnPages = false;
}

private void initializeCitationAdapter(XTextDocument doc) throws WrappedTargetException, NoSuchElementException {
private void initializeCitationAdapter(XTextDocument doc) throws Exception {
this.cslCitationOOAdapter = new CSLCitationOOAdapter(doc);
this.cslCitationOOAdapter.readExistingMarks();
}

public void guiActionSelectDocument(boolean autoSelectForSingle) throws WrappedTargetException, NoSuchElementException {
public void guiActionSelectDocument(boolean autoSelectForSingle) throws Exception {
final String errorTitle = Localization.lang("Problem connecting");

try {
Expand Down Expand Up @@ -634,7 +633,8 @@ public void guiActionInsertEntry(List<BibEntry> entries,
| NotRemoveableException ex) {
LOGGER.warn("Could not insert entry", ex);
OOError.fromMisc(ex).setTitle(errorTitle).showErrorDialog(dialogService);
} catch (Exception e) {
} catch (
Exception e) {
throw new RuntimeException(e);
} finally {
UnoUndo.leaveUndoContext(doc);
Expand Down Expand Up @@ -938,13 +938,15 @@ public void guiActionUpdateDocument(List<BibDatabase> databases, OOStyle style)
} catch (NoDocumentException
| NoSuchElementException e) {
throw new RuntimeException(e);
} catch (
Exception e) {
throw new RuntimeException(e);
} finally {
UnoUndo.leaveUndoContext(doc);
fcursor.get().restore(doc);
}
} catch (CreationException
| WrappedTargetException
| com.sun.star.lang.IllegalArgumentException ex) {
} catch (
com.sun.star.lang.IllegalArgumentException ex) {
LOGGER.warn("Could not update CSL bibliography", ex);
OOError.fromMisc(ex).setTitle(errorTitle).showErrorDialog(dialogService);
}
Expand Down
7 changes: 5 additions & 2 deletions src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,9 @@ private void initPanel() {
} catch (WrappedTargetException
| NoSuchElementException ex) {
throw new RuntimeException(ex);
} catch (
Exception ex) {
throw new RuntimeException(ex);
}
});

Expand Down Expand Up @@ -433,8 +436,8 @@ protected OOBibBase call() throws BootstrapException, CreationException {

try {
ooBase.guiActionSelectDocument(true);
} catch (WrappedTargetException
| NoSuchElementException e) {
} catch (
Exception e) {
throw new RuntimeException(e);
}

Expand Down
10 changes: 7 additions & 3 deletions src/main/java/org/jabref/logic/citationstyle/CSLAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@
/**
* Provides an adapter class to CSL. It holds a CSL instance under the hood that is only recreated when
* the style changes.
*
* <p>
* Note on the API: The first call to {@link #makeBibliography} is expensive since the
* CSL instance will be created. As long as the style stays the same, we can reuse this instance. On style-change, the
* engine is re-instantiated. Therefore, the use-case of this class is many calls to {@link #makeBibliography} with the
* same style. Changing the output format is cheap.
*
* <p>
* Note on the implementation:
* The main function {@link #makeBibliography} will enforce
* synchronized calling. The main CSL engine under the hood is not thread-safe. Since this class is usually called from
Expand Down Expand Up @@ -52,10 +52,14 @@ public synchronized List<String> makeBibliography(List<BibEntry> bibEntries, Str
}

public synchronized Citation makeInText(List<BibEntry> bibEntries, String style, CitationStyleOutputFormat outputFormat, BibDatabaseContext databaseContext, BibEntryTypesManager entryTypesManager) throws IOException {
return makeInTextMulti(bibEntries, style, outputFormat, databaseContext, entryTypesManager).getFirst();
}

public synchronized List<Citation> makeInTextMulti(List<BibEntry> bibEntries, String style, CitationStyleOutputFormat outputFormat, BibDatabaseContext databaseContext, BibEntryTypesManager entryTypesManager) throws IOException {
dataProvider.setData(bibEntries, databaseContext, entryTypesManager);
initialize(style, outputFormat);
cslInstance.registerCitationItems(dataProvider.getIds());
return cslInstance.makeCitation(bibEntries.stream().map(entry -> entry.getCitationKey().orElse("")).toList()).getFirst();
return cslInstance.makeCitation(bibEntries.stream().map(entry -> entry.getCitationKey().orElse("")).toList());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ public static Citation generateInText(List<BibEntry> bibEntries, String style, C
return CSL_ADAPTER.makeInText(bibEntries, style, outputFormat, databaseContext, entryTypesManager);
}

public static List<Citation> generateInTextMulti(List<BibEntry> bibEntries, String style, CitationStyleOutputFormat outputFormat, BibDatabaseContext databaseContext, BibEntryTypesManager entryTypesManager) throws IOException {
return CSL_ADAPTER.makeInTextMulti(bibEntries, style, outputFormat, databaseContext, entryTypesManager);
}

/**
* Generates the citation for multiple entries at once.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.jabref.logic.openoffice.oocsltext;

import java.io.IOException;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
Expand All @@ -24,7 +23,6 @@
import com.sun.star.lang.WrappedTargetException;
import com.sun.star.text.XTextCursor;
import com.sun.star.text.XTextDocument;
import com.sun.star.uno.Exception;

/**
* This class processes CSL citations in JabRef and interacts directly with LibreOffice using an XTextDocument instance.
Expand All @@ -50,7 +48,7 @@ public void readExistingMarks() throws WrappedTargetException, NoSuchElementExce
* Comparable to LaTeX's \cite command.
*/
public void insertCitation(XTextCursor cursor, CitationStyle selectedStyle, List<BibEntry> entries, BibDatabaseContext bibDatabaseContext, BibEntryTypesManager bibEntryTypesManager)
throws CreationException, IOException, Exception {
throws java.lang.Exception {
String style = selectedStyle.getSource();
boolean isAlphanumeric = isAlphanumericStyle(selectedStyle);

Expand Down Expand Up @@ -79,7 +77,7 @@ public void insertCitation(XTextCursor cursor, CitationStyle selectedStyle, List
* @implNote Very similar to the {@link #insertCitation(XTextCursor, CitationStyle, List, BibDatabaseContext, BibEntryTypesManager)} method.insertInText method
*/
public void insertInTextCitation(XTextCursor cursor, CitationStyle selectedStyle, List<BibEntry> entries, BibDatabaseContext bibDatabaseContext, BibEntryTypesManager bibEntryTypesManager)
throws IOException, CreationException, Exception {
throws java.lang.Exception {
String style = selectedStyle.getSource();
boolean isAlphanumeric = isAlphanumericStyle(selectedStyle);

Expand Down Expand Up @@ -128,7 +126,7 @@ public void insertInTextCitation(XTextCursor cursor, CitationStyle selectedStyle
* Adds the entries to the list for which bibliography is to be generated.
*/
public void insertEmpty(XTextCursor cursor, List<BibEntry> entries)
throws CreationException, Exception {
throws java.lang.Exception {
for (BibEntry entry : entries) {
CSLReferenceMark mark = markManager.createReferenceMark(entry);
OOText emptyOOText = OOFormat.setLocaleNone(OOText.fromString(""));
Expand Down Expand Up @@ -194,7 +192,7 @@ public void insertBibliography(XTextCursor cursor, CitationStyle selectedStyle,
* Thus, in case of citations for a group of entries, we first insert the citation (text), then insert the invisible reference marks for each entry separately after it.
*/
private void insertMultipleReferenceMarks(XTextCursor cursor, List<BibEntry> entries, OOText ooText)
throws CreationException, Exception {
throws java.lang.Exception {
boolean preceedingSpaceExists;
XTextCursor checkCursor = cursor.getText().createTextCursorByRange(cursor.getStart());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,37 +17,49 @@
import com.sun.star.uno.Exception;
import com.sun.star.uno.UnoRuntime;
import io.github.thibaultmeyer.cuid.CUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.jabref.logic.openoffice.backend.NamedRangeReferenceMark.safeInsertSpacesBetweenReferenceMarks;

/**
* Class to handle a reference mark. See {@link CSLReferenceMarkManager} for the management of all reference marks.
*/
public class CSLReferenceMark {

private static final Logger LOGGER = LoggerFactory.getLogger(CSLReferenceMark.class);

private final ReferenceMark referenceMark;
private final XTextContent textContent;
private ReferenceMark referenceMark;
private XTextContent textContent;
private final String citationKey;
private int citationNumber;

public CSLReferenceMark(XNamed named, ReferenceMark referenceMark) {
this.referenceMark = referenceMark;
textContent = UnoRuntime.queryInterface(XTextContent.class, named);
}

public CSLReferenceMark(XNamed named, String name, String citationKey, Integer citationNumber, String uniqueId) {
referenceMark = new ReferenceMark(name, citationKey, citationNumber, uniqueId);
this.textContent = UnoRuntime.queryInterface(XTextContent.class, named);
this.citationKey = referenceMark.getCitationKey();
this.citationNumber = referenceMark.getCitationNumber();
}

public static CSLReferenceMark of(String citationKey, Integer citationNumber, XMultiServiceFactory factory) throws Exception {
public static CSLReferenceMark of(String citationKey, int citationNumber, XMultiServiceFactory factory) throws Exception {
String uniqueId = CUID.randomCUID2(8).toString();
String name = "JABREF_" + citationKey + " CID_" + citationNumber + " " + uniqueId;
XNamed named = UnoRuntime.queryInterface(XNamed.class, factory.createInstance("com.sun.star.text.ReferenceMark"));
named.setName(name);
return new CSLReferenceMark(named, name, citationKey, citationNumber, uniqueId);
ReferenceMark referenceMark = new ReferenceMark(name, citationKey, citationNumber, uniqueId);
return new CSLReferenceMark(named, referenceMark);
}

public String getCitationKey() {
return citationKey;
}

public int getCitationNumber() {
return citationNumber;
}

public void setCitationNumber(int number) {
this.citationNumber = number;
}

public XTextContent getTextContent() {
return textContent;
}

public String getName() {
return referenceMark.getName();
}

public void insertReferenceIntoOO(XTextDocument doc, XTextCursor position, OOText ooText, boolean insertSpaceBefore, boolean insertSpaceAfter, boolean withoutBrackets)
Expand Down Expand Up @@ -100,11 +112,37 @@ public void insertReferenceIntoOO(XTextDocument doc, XTextCursor position, OOTex
position.gotoRange(cursorAfter.getEnd(), false);
}

public XTextContent getTextContent() {
return textContent;
public void delete() throws Exception {
XTextRange range = textContent.getAnchor();
range.setString("");
XTextContent xTextContent = UnoRuntime.queryInterface(XTextContent.class, textContent);
range.getText().removeTextContent(xTextContent);
}

public String getName() {
return referenceMark.getName();
public void select() throws Exception {
XTextRange range = textContent.getAnchor();
XTextCursor cursor = range.getText().createTextCursorByRange(range);
cursor.gotoRange(range, true);
}

public void setText(String textString, boolean isRich) throws Exception, CreationException {
XTextRange range = textContent.getAnchor();
XTextCursor cursor = range.getText().createTextCursorByRange(range);
cursor.setString("");
if (isRich) {
// Get the XTextDocument from the cursor's text
XTextDocument xTextDocument = UnoRuntime.queryInterface(XTextDocument.class, cursor.getText());
OOTextIntoOO.write(xTextDocument, cursor, OOText.fromString(textString));
} else {
cursor.setString(textString);
}
}

public void updateTextContent(XTextContent newTextContent) {
this.textContent = newTextContent;
}

public void updateName(String newName) {
this.referenceMark = new ReferenceMark(newName, this.citationKey, this.citationNumber, this.referenceMark.getUniqueId());
}
}
Loading
Loading