use of com.sun.star.text.XTextContent in project jabref by JabRef.
the class OOBibBase method refreshCiteMarkersInternal.
private List<String> refreshCiteMarkersInternal(List<BibDatabase> databases, OOBibStyle style) throws WrappedTargetException, IllegalArgumentException, NoSuchElementException, UndefinedCharacterFormatException, UnknownPropertyException, PropertyVetoException, CreationException, BibEntryNotFoundException {
List<String> cited = findCitedKeys();
Map<String, BibDatabase> linkSourceBase = new HashMap<>();
Map<BibEntry, BibDatabase> entries = findCitedEntries(databases, cited, linkSourceBase);
XNameAccess xReferenceMarks = getReferenceMarks();
List<String> names;
if (style.isSortByPosition()) {
// We need to sort the reference marks according to their order of appearance:
names = sortedReferenceMarks;
} else if (style.isNumberEntries()) {
// We need to sort the reference marks according to the sorting of the bibliographic
// entries:
SortedMap<BibEntry, BibDatabase> newMap = new TreeMap<>(entryComparator);
for (Map.Entry<BibEntry, BibDatabase> bibtexEntryBibtexDatabaseEntry : entries.entrySet()) {
newMap.put(bibtexEntryBibtexDatabaseEntry.getKey(), bibtexEntryBibtexDatabaseEntry.getValue());
}
entries = newMap;
// Rebuild the list of cited keys according to the sort order:
cited.clear();
for (BibEntry entry : entries.keySet()) {
cited.add(entry.getCiteKeyOptional().orElse(null));
}
names = Arrays.asList(xReferenceMarks.getElementNames());
} else {
names = sortedReferenceMarks;
}
// Remove all reference marks that don't look like JabRef citations:
List<String> tmp = new ArrayList<>();
for (String name : names) {
if (CITE_PATTERN.matcher(name).find()) {
tmp.add(name);
}
}
names = tmp;
Map<String, Integer> numbers = new HashMap<>();
int lastNum = 0;
// First compute citation markers for all citations:
String[] citMarkers = new String[names.size()];
String[][] normCitMarkers = new String[names.size()][];
String[][] bibtexKeys = new String[names.size()][];
int minGroupingCount = style.getIntCitProperty(OOBibStyle.MINIMUM_GROUPING_COUNT);
int[] types = new int[names.size()];
for (int i = 0; i < names.size(); i++) {
Matcher citeMatcher = CITE_PATTERN.matcher(names.get(i));
if (citeMatcher.find()) {
String typeStr = citeMatcher.group(1);
int type = Integer.parseInt(typeStr);
// Remember the type in case we need to uniquefy.
types[i] = type;
String[] keys = citeMatcher.group(2).split(",");
bibtexKeys[i] = keys;
BibEntry[] cEntries = new BibEntry[keys.length];
for (int j = 0; j < cEntries.length; j++) {
BibDatabase database = linkSourceBase.get(keys[j]);
Optional<BibEntry> tmpEntry = Optional.empty();
if (database != null) {
tmpEntry = database.getEntryByKey(keys[j]);
}
if (tmpEntry.isPresent()) {
cEntries[j] = tmpEntry.get();
} else {
LOGGER.info("BibTeX key not found: '" + keys[j] + '\'');
LOGGER.info("Problem with reference mark: '" + names.get(i) + '\'');
cEntries[j] = new UndefinedBibtexEntry(keys[j]);
}
}
String[] normCitMarker = new String[keys.length];
String citationMarker;
if (style.isBibtexKeyCiteMarkers()) {
StringBuilder sb = new StringBuilder();
normCitMarkers[i] = new String[keys.length];
for (int j = 0; j < keys.length; j++) {
normCitMarkers[i][j] = cEntries[j].getCiteKeyOptional().orElse(null);
sb.append(cEntries[j].getCiteKeyOptional().orElse(""));
if (j < (keys.length - 1)) {
sb.append(',');
}
}
citationMarker = sb.toString();
} else if (style.isNumberEntries()) {
if (style.isSortByPosition()) {
// We have sorted the citation markers according to their order of appearance,
// so we simply count up for each marker referring to a new entry:
List<Integer> num = new ArrayList<>(keys.length);
for (int j = 0; j < keys.length; j++) {
if (cEntries[j] instanceof UndefinedBibtexEntry) {
num.add(j, -1);
} else {
num.add(j, lastNum + 1);
if (numbers.containsKey(keys[j])) {
num.set(j, numbers.get(keys[j]));
} else {
numbers.put(keys[j], num.get(j));
lastNum = num.get(j);
}
}
}
citationMarker = style.getNumCitationMarker(num, minGroupingCount, false);
for (int j = 0; j < keys.length; j++) {
normCitMarker[j] = style.getNumCitationMarker(Collections.singletonList(num.get(j)), minGroupingCount, false);
}
} else {
// We need to find the number of the cited entry in the bibliography,
// and use that number for the cite marker:
List<Integer> num = findCitedEntryIndex(names.get(i), cited);
if (num.isEmpty()) {
throw new BibEntryNotFoundException(names.get(i), Localization.lang("Could not resolve BibTeX entry for citation marker '%0'.", names.get(i)));
} else {
citationMarker = style.getNumCitationMarker(num, minGroupingCount, false);
}
for (int j = 0; j < keys.length; j++) {
List<Integer> list = new ArrayList<>(1);
list.add(num.get(j));
normCitMarker[j] = style.getNumCitationMarker(list, minGroupingCount, false);
}
}
} else {
if (cEntries.length > 1) {
if (style.getBooleanCitProperty(OOBibStyle.MULTI_CITE_CHRONOLOGICAL)) {
Arrays.sort(cEntries, yearAuthorTitleComparator);
} else {
Arrays.sort(cEntries, entryComparator);
}
// Update key list to match the new sorting:
for (int j = 0; j < cEntries.length; j++) {
bibtexKeys[i][j] = cEntries[j].getCiteKeyOptional().orElse(null);
}
}
citationMarker = style.getCitationMarker(Arrays.asList(cEntries), entries, type == OOBibBase.AUTHORYEAR_PAR, null, null);
// We need "normalized" (in parenthesis) markers for uniqueness checking purposes:
for (int j = 0; j < cEntries.length; j++) {
normCitMarker[j] = style.getCitationMarker(Collections.singletonList(cEntries[j]), entries, true, null, new int[] { -1 });
}
}
citMarkers[i] = citationMarker;
normCitMarkers[i] = normCitMarker;
}
}
uniquefiers.clear();
if (!style.isBibtexKeyCiteMarkers() && !style.isNumberEntries()) {
// See if there are duplicate citations marks referring to different entries. If so, we need to
// use uniquefiers:
Map<String, List<String>> refKeys = new HashMap<>();
Map<String, List<Integer>> refNums = new HashMap<>();
for (int i = 0; i < citMarkers.length; i++) {
// compare normalized markers, since the actual markers can be different
String[] markers = normCitMarkers[i];
for (int j = 0; j < markers.length; j++) {
String marker = markers[j];
String currentKey = bibtexKeys[i][j];
if (refKeys.containsKey(marker)) {
// Ok, we have seen this exact marker before.
if (!refKeys.get(marker).contains(currentKey)) {
// ... but not for this entry.
refKeys.get(marker).add(currentKey);
refNums.get(marker).add(i);
}
} else {
List<String> l = new ArrayList<>(1);
l.add(currentKey);
refKeys.put(marker, l);
List<Integer> l2 = new ArrayList<>(1);
l2.add(i);
refNums.put(marker, l2);
}
}
}
// Go through the collected lists and see where we need to uniquefy:
for (Map.Entry<String, List<String>> stringListEntry : refKeys.entrySet()) {
List<String> keys = stringListEntry.getValue();
if (keys.size() > 1) {
// This marker appears for more than one unique entry:
int uniq = 'a';
for (String key : keys) {
// Update the map of uniquefiers for the benefit of both the following generation of new
// citation markers, and for the method that builds the bibliography:
uniquefiers.put(key, String.valueOf((char) uniq));
uniq++;
}
}
}
// Finally, go through all citation markers, and update those referring to entries in our current list:
int maxAuthorsFirst = style.getIntCitProperty(OOBibStyle.MAX_AUTHORS_FIRST);
Set<String> seenBefore = new HashSet<>();
for (int j = 0; j < bibtexKeys.length; j++) {
boolean needsChange = false;
int[] firstLimAuthors = new int[bibtexKeys[j].length];
String[] uniquif = new String[bibtexKeys[j].length];
BibEntry[] cEntries = new BibEntry[bibtexKeys[j].length];
for (int k = 0; k < bibtexKeys[j].length; k++) {
String currentKey = bibtexKeys[j][k];
firstLimAuthors[k] = -1;
if (maxAuthorsFirst > 0) {
if (!seenBefore.contains(currentKey)) {
firstLimAuthors[k] = maxAuthorsFirst;
}
seenBefore.add(currentKey);
}
String uniq = uniquefiers.get(currentKey);
Optional<BibEntry> tmpEntry = Optional.empty();
if (uniq == null) {
if (firstLimAuthors[k] > 0) {
needsChange = true;
BibDatabase database = linkSourceBase.get(currentKey);
if (database != null) {
tmpEntry = database.getEntryByKey(currentKey);
}
} else {
BibDatabase database = linkSourceBase.get(currentKey);
if (database != null) {
tmpEntry = database.getEntryByKey(currentKey);
}
}
uniquif[k] = "";
} else {
needsChange = true;
BibDatabase database = linkSourceBase.get(currentKey);
if (database != null) {
tmpEntry = database.getEntryByKey(currentKey);
}
uniquif[k] = uniq;
}
if (tmpEntry.isPresent()) {
cEntries[k] = tmpEntry.get();
}
}
if (needsChange) {
citMarkers[j] = style.getCitationMarker(Arrays.asList(cEntries), entries, types[j] == OOBibBase.AUTHORYEAR_PAR, uniquif, firstLimAuthors);
}
}
}
// Refresh all reference marks with the citation markers we computed:
boolean hadBibSection = getBookmarkRange(OOBibBase.BIB_SECTION_NAME) != null;
// Check if we are supposed to set a character format for citations:
boolean mustTestCharFormat = style.isFormatCitations();
for (int i = 0; i < names.size(); i++) {
Object referenceMark = xReferenceMarks.getByName(names.get(i));
XTextContent bookmark = UnoRuntime.queryInterface(XTextContent.class, referenceMark);
XTextCursor cursor = bookmark.getAnchor().getText().createTextCursorByRange(bookmark.getAnchor());
if (mustTestCharFormat) {
// If we are supposed to set character format for citations, must run a test before we
// delete old citation markers. Otherwise, if the specified character format doesn't
// exist, we end up deleting the markers before the process crashes due to a the missing
// format, with catastrophic consequences for the user.
// need to do this only once
mustTestCharFormat = false;
XPropertySet xCursorProps = UnoRuntime.queryInterface(XPropertySet.class, cursor);
String charStyle = style.getCitationCharacterFormat();
try {
xCursorProps.setPropertyValue(CHAR_STYLE_NAME, charStyle);
} catch (UnknownPropertyException | PropertyVetoException | IllegalArgumentException | WrappedTargetException ex) {
throw new UndefinedCharacterFormatException(charStyle);
}
}
text.removeTextContent(bookmark);
insertReferenceMark(names.get(i), citMarkers[i], cursor, types[i] != OOBibBase.INVISIBLE_CIT, style);
if (hadBibSection && (getBookmarkRange(OOBibBase.BIB_SECTION_NAME) == null)) {
// We have overwritten the marker for the start of the reference list.
// We need to add it again.
cursor.collapseToEnd();
OOUtil.insertParagraphBreak(text, cursor);
insertBookMark(OOBibBase.BIB_SECTION_NAME, cursor);
}
}
List<String> unresolvedKeys = new ArrayList<>();
for (BibEntry entry : entries.keySet()) {
if (entry instanceof UndefinedBibtexEntry) {
String key = ((UndefinedBibtexEntry) entry).getKey();
if (!unresolvedKeys.contains(key)) {
unresolvedKeys.add(key);
}
}
}
return unresolvedKeys;
}
use of com.sun.star.text.XTextContent in project jabref by JabRef.
the class OOBibBase method getBookmarkRange.
/**
* Get the XTextRange corresponding to the named bookmark.
* @param name The name of the bookmark to find.
* @return The XTextRange for the bookmark.
* @throws WrappedTargetException
* @throws NoSuchElementException
*/
private XTextRange getBookmarkRange(String name) throws NoSuchElementException, WrappedTargetException {
XNameAccess xNamedBookmarks = getBookmarks();
// retrieve bookmark by name
if (!xNamedBookmarks.hasByName(name)) {
return null;
}
Object foundBookmark = xNamedBookmarks.getByName(name);
XTextContent xFoundBookmark = UnoRuntime.queryInterface(XTextContent.class, foundBookmark);
return xFoundBookmark.getAnchor();
}
use of com.sun.star.text.XTextContent in project jabref by JabRef.
the class OOBibBase method getSortedReferenceMarks.
private List<String> getSortedReferenceMarks(final XNameAccess nameAccess) throws WrappedTargetException, NoSuchElementException {
XTextViewCursorSupplier cursorSupplier = UnoRuntime.queryInterface(XTextViewCursorSupplier.class, mxDoc.getCurrentController());
XTextViewCursor viewCursor = cursorSupplier.getViewCursor();
XTextRange initialPos = viewCursor.getStart();
List<String> names = Arrays.asList(nameAccess.getElementNames());
List<Point> positions = new ArrayList<>(names.size());
for (String name : names) {
XTextContent textContent = UnoRuntime.queryInterface(XTextContent.class, nameAccess.getByName(name));
XTextRange range = textContent.getAnchor();
// Check if we are inside a footnote:
if (UnoRuntime.queryInterface(XFootnote.class, range.getText()) != null) {
// Find the linking footnote marker:
XFootnote footer = UnoRuntime.queryInterface(XFootnote.class, range.getText());
// The footnote's anchor gives the correct position in the text:
range = footer.getAnchor();
}
positions.add(findPosition(viewCursor, range));
}
Set<ComparableMark> set = new TreeSet<>();
for (int i = 0; i < positions.size(); i++) {
set.add(new ComparableMark(names.get(i), positions.get(i)));
}
List<String> result = new ArrayList<>(set.size());
for (ComparableMark mark : set) {
result.add(mark.getName());
}
viewCursor.gotoRange(initialPos, false);
return result;
}
Aggregations