diff --git a/src/main/java/org/jabref/logic/openoffice/action/EditInsert.java b/src/main/java/org/jabref/logic/openoffice/action/EditInsert.java new file mode 100644 index 00000000000..0004d3fe6db --- /dev/null +++ b/src/main/java/org/jabref/logic/openoffice/action/EditInsert.java @@ -0,0 +1,118 @@ +package org.jabref.logic.openoffice.action; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import org.jabref.logic.openoffice.frontend.OOFrontend; +import org.jabref.logic.openoffice.frontend.UpdateCitationMarkers; +import org.jabref.logic.openoffice.style.OOBibStyle; +import org.jabref.model.database.BibDatabase; +import org.jabref.model.entry.BibEntry; +import org.jabref.model.openoffice.ootext.OOText; +import org.jabref.model.openoffice.style.Citation; +import org.jabref.model.openoffice.style.CitationMarkerEntry; +import org.jabref.model.openoffice.style.CitationType; +import org.jabref.model.openoffice.style.NonUniqueCitationMarker; +import org.jabref.model.openoffice.style.OODataModel; +import org.jabref.model.openoffice.uno.CreationException; +import org.jabref.model.openoffice.uno.NoDocumentException; +import org.jabref.model.openoffice.uno.UnoScreenRefresh; +import org.jabref.model.openoffice.util.OOListUtil; +import org.jabref.model.strings.StringUtil; + +import com.sun.star.beans.IllegalTypeException; +import com.sun.star.beans.NotRemoveableException; +import com.sun.star.beans.PropertyVetoException; +import com.sun.star.lang.WrappedTargetException; +import com.sun.star.text.XTextCursor; +import com.sun.star.text.XTextDocument; + +public class EditInsert { + + private EditInsert() { + /**/ + } + + /** + * In insertEntry we receive BibEntry values from the GUI. + * + * In the document we store citations by their citation key. + * + * If the citation key is missing, the best we can do is to notify the user. Or the programmer, + * that we cannot accept such input. + * + */ + private static String insertEntryGetCitationKey(BibEntry entry) { + Optional key = entry.getCitationKey(); + if (key.isEmpty()) { + throw new IllegalArgumentException("insertEntryGetCitationKey: cannot cite entries without citation key"); + } + return key.get(); + } + + /** + * @param cursor Where to insert. + * @param pageInfo A single pageInfo for a list of entries. This is what we get from the GUI. + */ + public static void insertCitationGroup(XTextDocument doc, + OOFrontend frontend, + XTextCursor cursor, + List entries, + BibDatabase database, + OOBibStyle style, + CitationType citationType, + String pageInfo) + throws + NoDocumentException, + NotRemoveableException, + WrappedTargetException, + PropertyVetoException, + CreationException, + IllegalTypeException { + + List citationKeys = OOListUtil.map(entries, EditInsert::insertEntryGetCitationKey); + + final int totalEntries = entries.size(); + List> pageInfos = OODataModel.fakePageInfos(pageInfo, totalEntries); + + List citations = new ArrayList<>(totalEntries); + for (int i = 0; i < totalEntries; i++) { + Citation cit = new Citation(citationKeys.get(i)); + cit.lookupInDatabases(Collections.singletonList(database)); + cit.setPageInfo(pageInfos.get(i)); + citations.add(cit); + } + + // The text we insert + OOText citeText = null; + if (style.isNumberEntries()) { + citeText = OOText.fromString("[-]"); // A dash only. Only refresh later. + } else { + citeText = style.createCitationMarker(citations, + citationType.inParenthesis(), + NonUniqueCitationMarker.FORGIVEN); + } + + if (StringUtil.isBlank(OOText.toString(citeText))) { + citeText = OOText.fromString("[?]"); + } + + try { + UnoScreenRefresh.lockControllers(doc); + UpdateCitationMarkers.createAndFillCitationGroup(frontend, + doc, + citationKeys, + pageInfos, + citationType, + citeText, + cursor, + style, + true /* insertSpaceAfter */); + } finally { + UnoScreenRefresh.unlockControllers(doc); + } + + } +} diff --git a/src/main/java/org/jabref/logic/openoffice/action/EditMerge.java b/src/main/java/org/jabref/logic/openoffice/action/EditMerge.java new file mode 100644 index 00000000000..f91e8aec93d --- /dev/null +++ b/src/main/java/org/jabref/logic/openoffice/action/EditMerge.java @@ -0,0 +1,344 @@ +package org.jabref.logic.openoffice.action; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.jabref.logic.openoffice.frontend.OOFrontend; +import org.jabref.logic.openoffice.frontend.UpdateCitationMarkers; +import org.jabref.logic.openoffice.style.OOBibStyle; +import org.jabref.model.openoffice.ootext.OOText; +import org.jabref.model.openoffice.style.Citation; +import org.jabref.model.openoffice.style.CitationGroup; +import org.jabref.model.openoffice.style.CitationType; +import org.jabref.model.openoffice.uno.CreationException; +import org.jabref.model.openoffice.uno.NoDocumentException; +import org.jabref.model.openoffice.uno.UnoScreenRefresh; +import org.jabref.model.openoffice.uno.UnoTextRange; +import org.jabref.model.openoffice.util.OOListUtil; + +import com.sun.star.beans.IllegalTypeException; +import com.sun.star.beans.NotRemoveableException; +import com.sun.star.beans.PropertyVetoException; +import com.sun.star.lang.WrappedTargetException; +import com.sun.star.text.XTextCursor; +import com.sun.star.text.XTextDocument; +import com.sun.star.text.XTextRange; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class EditMerge { + + private static final Logger LOGGER = LoggerFactory.getLogger(EditMerge.class); + + private EditMerge() { + // hide constructor + } + + /* + * @return true if modified document + */ + public static boolean mergeCitationGroups(XTextDocument doc, OOFrontend frontend, OOBibStyle style) + throws + CreationException, + IllegalArgumentException, + IllegalTypeException, + NoDocumentException, + NotRemoveableException, + PropertyVetoException, + WrappedTargetException { + + boolean madeModifications; + + try { + UnoScreenRefresh.lockControllers(doc); + + List joinableGroups = EditMerge.scan(doc, frontend); + + for (JoinableGroupData joinableGroupData : joinableGroups) { + + List groups = joinableGroupData.group; + + List newCitations = (groups.stream() + .flatMap(group -> group.citationsInStorageOrder.stream()) + .collect(Collectors.toList())); + + CitationType citationType = groups.get(0).citationType; + List> pageInfos = frontend.backend.combinePageInfos(groups); + + frontend.removeCitationGroups(groups, doc); + XTextCursor textCursor = joinableGroupData.groupCursor; + textCursor.setString(""); // Also remove the spaces between. + + List citationKeys = OOListUtil.map(newCitations, Citation::getCitationKey); + + /* insertSpaceAfter: no, it is already there (or could be) */ + boolean insertSpaceAfter = false; + UpdateCitationMarkers.createAndFillCitationGroup(frontend, + doc, + citationKeys, + pageInfos, + citationType, + OOText.fromString("tmp"), + textCursor, + style, + insertSpaceAfter); + } + + madeModifications = !joinableGroups.isEmpty(); + + } finally { + UnoScreenRefresh.unlockControllers(doc); + } + + return madeModifications; + } + + private static class JoinableGroupData { + /** A list of consecutive citation groups only separated by spaces. */ + List group; + + /** A cursor covering the XTextRange of each entry in group (and the spaces between them) */ + XTextCursor groupCursor; + + JoinableGroupData(List group, XTextCursor groupCursor) { + this.group = group; + this.groupCursor = groupCursor; + } + } + + private static class ScanState { + + // Citation groups in the current group + List currentGroup; + + // A cursor that covers the Citation groups in currentGroup, including the space between + // them. + // null if currentGroup.isEmpty() + XTextCursor currentGroupCursor; + + // A cursor starting at the end of the last CitationGroup in + // currentGroup. null if currentGroup.isEmpty() + XTextCursor cursorBetween; + + // The last element of currentGroup. + // null if currentGroup.isEmpty() + CitationGroup prev; + + // The XTextRange for prev. + // null if currentGroup.isEmpty() + XTextRange prevRange; + + ScanState() { + reset(); + } + + void reset() { + currentGroup = new ArrayList<>(); + currentGroupCursor = null; + cursorBetween = null; + prev = null; + prevRange = null; + } + } + + /** + * Decide if group could be added to state.currentGroup + * + * @param group The CitationGroup to test + * @param currentRange The XTextRange corresponding to group. + * + * @return false if cannot add, true if can. If returned true, then state.cursorBetween and + * state.currentGroupCursor are expanded to end at the start of currentRange. + */ + private static boolean checkAddToGroup(ScanState state, CitationGroup group, XTextRange currentRange) { + + if (state.currentGroup.isEmpty()) { + return false; + } + + Objects.requireNonNull(state.currentGroupCursor); + Objects.requireNonNull(state.cursorBetween); + Objects.requireNonNull(state.prev); + Objects.requireNonNull(state.prevRange); + + // Only combine (Author 2000) type citations + if (group.citationType != CitationType.AUTHORYEAR_PAR) { + return false; + } + + if (state.prev != null) { + + // Even if we combine AUTHORYEAR_INTEXT citations, we would not mix them with AUTHORYEAR_PAR + if (group.citationType != state.prev.citationType) { + return false; + } + + if (!UnoTextRange.comparables(state.prevRange, currentRange)) { + return false; + } + + // Sanity check: the current range should start later than the previous. + int textOrder = UnoTextRange.compareStarts(state.prevRange, currentRange); + if (textOrder != (-1)) { + String msg = + String.format("MergeCitationGroups:" + + " \"%s\" supposed to be followed by \"%s\"," + + " but %s", + state.prevRange.getString(), + currentRange.getString(), + ((textOrder == 0) + ? "they start at the same position" + : "the start of the latter precedes the start of the first")); + LOGGER.warn(msg); + return false; + } + } + + if (state.cursorBetween == null) { + return false; + } + + Objects.requireNonNull(state.cursorBetween); + Objects.requireNonNull(state.currentGroupCursor); + + // assume: currentGroupCursor.getEnd() == cursorBetween.getEnd() + if (UnoTextRange.compareEnds(state.cursorBetween, state.currentGroupCursor) != 0) { + LOGGER.warn("MergeCitationGroups: cursorBetween.end != currentGroupCursor.end"); + throw new IllegalStateException("MergeCitationGroups failed"); + } + + /* + * Try to expand state.currentGroupCursor and state.cursorBetween by going right to reach + * rangeStart. + */ + XTextRange rangeStart = currentRange.getStart(); + boolean couldExpand = true; + XTextCursor thisCharCursor = + (currentRange.getText().createTextCursorByRange(state.cursorBetween.getEnd())); + + while (couldExpand && (UnoTextRange.compareEnds(state.cursorBetween, rangeStart) < 0)) { + // + // Check that we only walk through inline whitespace. + // + couldExpand = thisCharCursor.goRight((short) 1, true); + String thisChar = thisCharCursor.getString(); + thisCharCursor.collapseToEnd(); + if (thisChar.isEmpty() || "\n".equals(thisChar) || !thisChar.trim().isEmpty()) { + couldExpand = false; + if (!thisChar.isEmpty()) { + thisCharCursor.goLeft((short) 1, false); + } + break; + } + state.cursorBetween.goRight((short) 1, true); + state.currentGroupCursor.goRight((short) 1, true); + + // These two should move in sync: + if (UnoTextRange.compareEnds(state.cursorBetween, state.currentGroupCursor) != 0) { + LOGGER.warn("MergeCitationGroups: cursorBetween.end != currentGroupCursor.end (during expand)"); + throw new IllegalStateException("MergeCitationGroups failed"); + } + } + + return couldExpand; + } + + /** + * Add group to state.currentGroup + * Set state.cursorBetween to start at currentRange.getEnd() + * Expand state.currentGroupCursor to also cover currentRange + * Set state.prev to group, state.prevRange to currentRange + */ + private static void addToCurrentGroup(ScanState state, CitationGroup group, XTextRange currentRange) { + final boolean isNewGroup = state.currentGroup.isEmpty(); + if (!isNewGroup) { + Objects.requireNonNull(state.currentGroupCursor); + Objects.requireNonNull(state.cursorBetween); + Objects.requireNonNull(state.prev); + Objects.requireNonNull(state.prevRange); + } + + // Add the current entry to a group. + state.currentGroup.add(group); + + // Set up cursorBetween to start at currentRange.getEnd() + XTextRange rangeEnd = currentRange.getEnd(); + state.cursorBetween = currentRange.getText().createTextCursorByRange(rangeEnd); + + // If new group, create currentGroupCursor + if (isNewGroup) { + state.currentGroupCursor = (currentRange.getText() + .createTextCursorByRange(currentRange.getStart())); + } + + // include currentRange in currentGroupCursor + state.currentGroupCursor.goRight((short) (currentRange.getString().length()), true); + + if (UnoTextRange.compareEnds(state.cursorBetween, state.currentGroupCursor) != 0) { + LOGGER.warn("MergeCitationGroups: cursorBetween.end != currentGroupCursor.end"); + throw new IllegalStateException("MergeCitationGroups failed"); + } + + /* Store data about last entry in currentGroup */ + state.prev = group; + state.prevRange = currentRange; + } + + /** + * Scan the document for joinable groups. Return those found. + */ + private static List scan(XTextDocument doc, OOFrontend frontend) + throws + NoDocumentException, + WrappedTargetException { + List result = new ArrayList<>(); + + List groups = frontend.getCitationGroupsSortedWithinPartitions(doc, false /* mapFootnotesToFootnoteMarks */); + if (groups.isEmpty()) { + return result; + } + + ScanState state = new ScanState(); + + for (CitationGroup group : groups) { + + XTextRange currentRange = (frontend.getMarkRange(doc, group) + .orElseThrow(IllegalStateException::new)); + + /* + * Decide if we add group to the group. False when the group is empty. + */ + boolean addToGroup = checkAddToGroup(state, group, currentRange); + + /* + * Even if we do not add it to an existing group, we might use it to start a new group. + * + * Can it start a new group? + */ + boolean canStartGroup = (group.citationType == CitationType.AUTHORYEAR_PAR); + + if (!addToGroup) { + // close currentGroup + if (state.currentGroup.size() > 1) { + result.add(new JoinableGroupData(state.currentGroup, state.currentGroupCursor)); + } + // Start a new, empty group + state.reset(); + } + + if (addToGroup || canStartGroup) { + addToCurrentGroup(state, group, currentRange); + } + } + + // close currentGroup + if (state.currentGroup.size() > 1) { + result.add(new JoinableGroupData(state.currentGroup, state.currentGroupCursor)); + } + return result; + } + +} diff --git a/src/main/java/org/jabref/logic/openoffice/action/EditSeparate.java b/src/main/java/org/jabref/logic/openoffice/action/EditSeparate.java new file mode 100644 index 00000000000..66630a6f8d0 --- /dev/null +++ b/src/main/java/org/jabref/logic/openoffice/action/EditSeparate.java @@ -0,0 +1,99 @@ +package org.jabref.logic.openoffice.action; + +import java.util.List; + +import org.jabref.logic.openoffice.frontend.OOFrontend; +import org.jabref.logic.openoffice.frontend.UpdateCitationMarkers; +import org.jabref.logic.openoffice.style.OOBibStyle; +import org.jabref.logic.openoffice.style.OOProcess; +import org.jabref.model.database.BibDatabase; +import org.jabref.model.openoffice.ootext.OOText; +import org.jabref.model.openoffice.style.Citation; +import org.jabref.model.openoffice.style.CitationGroup; +import org.jabref.model.openoffice.uno.CreationException; +import org.jabref.model.openoffice.uno.NoDocumentException; +import org.jabref.model.openoffice.uno.UnoScreenRefresh; + +import com.sun.star.beans.IllegalTypeException; +import com.sun.star.beans.NotRemoveableException; +import com.sun.star.beans.PropertyVetoException; +import com.sun.star.lang.WrappedTargetException; +import com.sun.star.text.XTextCursor; +import com.sun.star.text.XTextDocument; +import com.sun.star.text.XTextRange; + +public class EditSeparate { + + private EditSeparate() { + /**/ + } + + public static boolean separateCitations(XTextDocument doc, + OOFrontend frontend, + List databases, + OOBibStyle style) + throws + CreationException, + IllegalTypeException, + NoDocumentException, + NotRemoveableException, + PropertyVetoException, + WrappedTargetException, + com.sun.star.lang.IllegalArgumentException { + + boolean madeModifications = false; + + // To reduce surprises in JabRef52 mode, impose localOrder to + // decide the visually last Citation in the group. Unless the + // style changed since refresh this is the last on the screen + // as well. + frontend.citationGroups.lookupCitations(databases); + frontend.citationGroups.imposeLocalOrder(OOProcess.comparatorForMulticite(style)); + + List groups = frontend.citationGroups.getCitationGroupsUnordered(); + + try { + UnoScreenRefresh.lockControllers(doc); + + for (CitationGroup group : groups) { + + XTextRange range1 = (frontend + .getMarkRange(doc, group) + .orElseThrow(IllegalStateException::new)); + XTextCursor textCursor = range1.getText().createTextCursorByRange(range1); + + List citations = group.citationsInStorageOrder; + if (citations.size() <= 1) { + continue; + } + + frontend.removeCitationGroup(group, doc); + // Now we own the content of citations + + // Create a citation group for each citation. + final int last = citations.size() - 1; + for (int i = 0; i < citations.size(); i++) { + boolean insertSpaceAfter = (i != last); + Citation citation = citations.get(i); + + UpdateCitationMarkers.createAndFillCitationGroup(frontend, + doc, + List.of(citation.citationKey), + List.of(citation.getPageInfo()), + group.citationType, + OOText.fromString(citation.citationKey), + textCursor, + style, + insertSpaceAfter); + + textCursor.collapseToEnd(); + } + + madeModifications = true; + } + } finally { + UnoScreenRefresh.unlockControllers(doc); + } + return madeModifications; + } +} diff --git a/src/main/java/org/jabref/logic/openoffice/action/ExportCited.java b/src/main/java/org/jabref/logic/openoffice/action/ExportCited.java new file mode 100644 index 00000000000..c38cd4fd4cc --- /dev/null +++ b/src/main/java/org/jabref/logic/openoffice/action/ExportCited.java @@ -0,0 +1,98 @@ +package org.jabref.logic.openoffice.action; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.jabref.logic.openoffice.frontend.OOFrontend; +import org.jabref.model.database.BibDatabase; +import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.field.StandardField; +import org.jabref.model.openoffice.style.CitedKey; +import org.jabref.model.openoffice.style.CitedKeys; +import org.jabref.model.openoffice.uno.NoDocumentException; + +import com.sun.star.lang.WrappedTargetException; +import com.sun.star.text.XTextDocument; + +public class ExportCited { + + private ExportCited() { + /**/ + } + + public static class GenerateDatabaseResult { + /** + * null: not done; isEmpty: no unresolved + */ + public final List unresolvedKeys; + public final BibDatabase newDatabase; + + GenerateDatabaseResult(List unresolvedKeys, BibDatabase newDatabase) { + this.unresolvedKeys = unresolvedKeys; + this.newDatabase = newDatabase; + } + } + + /** + * + * @param databases The databases to look up the citation keys in the document from. + * @return A new database, with cloned entries. + * + * If a key is not found, it is added to result.unresolvedKeys + * + * Cross references (in StandardField.CROSSREF) are followed (not recursively): + * If the referenced entry is found, it is included in the result. + * If it is not found, it is silently ignored. + */ + public static GenerateDatabaseResult generateDatabase(XTextDocument doc, List databases) + throws + NoDocumentException, + WrappedTargetException { + + OOFrontend frontend = new OOFrontend(doc); + CitedKeys citationKeys = frontend.citationGroups.getCitedKeysUnordered(); + citationKeys.lookupInDatabases(databases); + + List unresolvedKeys = new ArrayList<>(); + BibDatabase resultDatabase = new BibDatabase(); + + List entriesToInsert = new ArrayList<>(); + Set seen = new HashSet<>(); // Only add crossReference once. + + for (CitedKey citation : citationKeys.values()) { + if (citation.getLookupResult().isEmpty()) { + unresolvedKeys.add(citation.citationKey); + continue; + } else { + BibEntry entry = citation.getLookupResult().get().entry; + BibDatabase loopDatabase = citation.getLookupResult().get().database; + + // If entry found + BibEntry clonedEntry = (BibEntry) entry.clone(); + + // Insert a copy of the entry + entriesToInsert.add(clonedEntry); + + // Check if the cloned entry has a cross-reference field + clonedEntry + .getField(StandardField.CROSSREF) + .ifPresent(crossReference -> { + boolean isNew = !seen.contains(crossReference); + if (isNew) { + // Add it if it is in the current library + loopDatabase + .getEntryByCitationKey(crossReference) + .ifPresent(entriesToInsert::add); + seen.add(crossReference); + } + }); + } + } + + resultDatabase.insertEntries(entriesToInsert); + return new GenerateDatabaseResult(unresolvedKeys, resultDatabase); + } + +} diff --git a/src/main/java/org/jabref/logic/openoffice/action/ManageCitations.java b/src/main/java/org/jabref/logic/openoffice/action/ManageCitations.java new file mode 100644 index 00000000000..c8234df9ca0 --- /dev/null +++ b/src/main/java/org/jabref/logic/openoffice/action/ManageCitations.java @@ -0,0 +1,38 @@ +package org.jabref.logic.openoffice.action; + +import java.util.List; + +import org.jabref.logic.openoffice.frontend.OOFrontend; +import org.jabref.model.openoffice.CitationEntry; +import org.jabref.model.openoffice.uno.NoDocumentException; + +import com.sun.star.beans.IllegalTypeException; +import com.sun.star.beans.PropertyVetoException; +import com.sun.star.lang.WrappedTargetException; +import com.sun.star.text.XTextDocument; + +public class ManageCitations { + + private ManageCitations() { + /**/ + } + + public static List getCitationEntries(XTextDocument doc) + throws + NoDocumentException, + WrappedTargetException { + OOFrontend frontend = new OOFrontend(doc); + return frontend.getCitationEntries(doc); + } + + public static void applyCitationEntries(XTextDocument doc, List citationEntries) + throws + NoDocumentException, + PropertyVetoException, + IllegalTypeException, + WrappedTargetException, + IllegalArgumentException { + OOFrontend frontend = new OOFrontend(doc); + frontend.applyCitationEntries(doc, citationEntries); + } +} diff --git a/src/main/java/org/jabref/logic/openoffice/action/Update.java b/src/main/java/org/jabref/logic/openoffice/action/Update.java new file mode 100644 index 00000000000..80263833aec --- /dev/null +++ b/src/main/java/org/jabref/logic/openoffice/action/Update.java @@ -0,0 +1,133 @@ +package org.jabref.logic.openoffice.action; + +import java.util.List; + +import org.jabref.logic.openoffice.frontend.OOFrontend; +import org.jabref.logic.openoffice.frontend.UpdateBibliography; +import org.jabref.logic.openoffice.frontend.UpdateCitationMarkers; +import org.jabref.logic.openoffice.style.OOBibStyle; +import org.jabref.logic.openoffice.style.OOProcess; +import org.jabref.model.database.BibDatabase; +import org.jabref.model.openoffice.rangesort.FunctionalTextViewCursor; +import org.jabref.model.openoffice.uno.CreationException; +import org.jabref.model.openoffice.uno.NoDocumentException; +import org.jabref.model.openoffice.uno.UnoScreenRefresh; + +import com.sun.star.lang.WrappedTargetException; +import com.sun.star.text.XTextDocument; + +/** + * Update document: citation marks and bibliography + */ +public class Update { + + static final boolean USE_LOCK_CONTROLLERS = true; + + private Update() { + /**/ + } + + /** + * @return the list of unresolved citation keys + */ + private static List updateDocument(XTextDocument doc, + OOFrontend frontend, + List databases, + OOBibStyle style, + FunctionalTextViewCursor fcursor, + boolean doUpdateBibliography, + boolean alwaysAddCitedOnPages) + throws + CreationException, + NoDocumentException, + WrappedTargetException, + com.sun.star.lang.IllegalArgumentException { + + frontend.imposeGlobalOrder(doc, fcursor); + OOProcess.produceCitationMarkers(frontend.citationGroups, databases, style); + + try { + if (USE_LOCK_CONTROLLERS) { + UnoScreenRefresh.lockControllers(doc); + } + + UpdateCitationMarkers.applyNewCitationMarkers(doc, frontend, style); + + if (doUpdateBibliography) { + UpdateBibliography.rebuildBibTextSection(doc, + frontend, + frontend.citationGroups.getBibliography().get(), + style, + alwaysAddCitedOnPages); + } + + return frontend.citationGroups.getUnresolvedKeys(); + } finally { + if (USE_LOCK_CONTROLLERS && UnoScreenRefresh.hasControllersLocked(doc)) { + UnoScreenRefresh.unlockControllers(doc); + } + } + } + + public static class SyncOptions { + + public final List databases; + boolean updateBibliography; + boolean alwaysAddCitedOnPages; + + public SyncOptions(List databases) { + this.databases = databases; + this.updateBibliography = false; + this.alwaysAddCitedOnPages = false; + } + + public SyncOptions setUpdateBibliography(boolean value) { + this.updateBibliography = value; + return this; + } + + public SyncOptions setAlwaysAddCitedOnPages(boolean value) { + this.alwaysAddCitedOnPages = value; + return this; + } + } + + public static List synchronizeDocument(XTextDocument doc, + OOFrontend frontend, + OOBibStyle style, + FunctionalTextViewCursor fcursor, + SyncOptions syncOptions) + throws + CreationException, + NoDocumentException, + WrappedTargetException, + com.sun.star.lang.IllegalArgumentException { + + return Update.updateDocument(doc, + frontend, + syncOptions.databases, + style, + fcursor, + syncOptions.updateBibliography, + syncOptions.alwaysAddCitedOnPages); + } + + /* + * Reread document before sync + */ + public static List resyncDocument(XTextDocument doc, + OOBibStyle style, + FunctionalTextViewCursor fcursor, + SyncOptions syncOptions) + throws + CreationException, + NoDocumentException, + WrappedTargetException, + com.sun.star.lang.IllegalArgumentException { + + OOFrontend frontend = new OOFrontend(doc); + + return Update.synchronizeDocument(doc, frontend, style, fcursor, syncOptions); + } + +}