Search in sources :

Example 6 with XTextContent

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;
}
Also used : WrappedTargetException(com.sun.star.lang.WrappedTargetException) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Matcher(java.util.regex.Matcher) ArrayList(java.util.ArrayList) XTextCursor(com.sun.star.text.XTextCursor) BibEntry(org.jabref.model.entry.BibEntry) UndefinedBibtexEntry(org.jabref.logic.openoffice.UndefinedBibtexEntry) List(java.util.List) ArrayList(java.util.ArrayList) JList(javax.swing.JList) IllegalArgumentException(com.sun.star.lang.IllegalArgumentException) HashSet(java.util.HashSet) BibEntry(org.jabref.model.entry.BibEntry) UndefinedBibtexEntry(org.jabref.logic.openoffice.UndefinedBibtexEntry) XNameAccess(com.sun.star.container.XNameAccess) UnknownPropertyException(com.sun.star.beans.UnknownPropertyException) Point(com.sun.star.awt.Point) XPropertySet(com.sun.star.beans.XPropertySet) PropertyVetoException(com.sun.star.beans.PropertyVetoException) XTextContent(com.sun.star.text.XTextContent) SortedMap(java.util.SortedMap) BibDatabase(org.jabref.model.database.BibDatabase) Map(java.util.Map) SortedMap(java.util.SortedMap) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) TreeMap(java.util.TreeMap)

Example 7 with XTextContent

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();
}
Also used : XTextContent(com.sun.star.text.XTextContent) XNameAccess(com.sun.star.container.XNameAccess)

Example 8 with XTextContent

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;
}
Also used : XTextRange(com.sun.star.text.XTextRange) ArrayList(java.util.ArrayList) Point(com.sun.star.awt.Point) Point(com.sun.star.awt.Point) XTextViewCursorSupplier(com.sun.star.text.XTextViewCursorSupplier) XFootnote(com.sun.star.text.XFootnote) XTextContent(com.sun.star.text.XTextContent) TreeSet(java.util.TreeSet) XTextViewCursor(com.sun.star.text.XTextViewCursor)

Aggregations

XTextContent (com.sun.star.text.XTextContent)8 Point (com.sun.star.awt.Point)4 PropertyVetoException (com.sun.star.beans.PropertyVetoException)4 UnknownPropertyException (com.sun.star.beans.UnknownPropertyException)4 IllegalArgumentException (com.sun.star.lang.IllegalArgumentException)4 WrappedTargetException (com.sun.star.lang.WrappedTargetException)4 IllegalTypeException (com.sun.star.beans.IllegalTypeException)3 NotRemoveableException (com.sun.star.beans.NotRemoveableException)3 PropertyExistException (com.sun.star.beans.PropertyExistException)3 BootstrapException (com.sun.star.comp.helper.BootstrapException)3 NoSuchElementException (com.sun.star.container.NoSuchElementException)3 XNameAccess (com.sun.star.container.XNameAccess)3 XNamed (com.sun.star.container.XNamed)3 DisposedException (com.sun.star.lang.DisposedException)3 XTextCursor (com.sun.star.text.XTextCursor)3 IOException (java.io.IOException)3 InvocationTargetException (java.lang.reflect.InvocationTargetException)3 MalformedURLException (java.net.MalformedURLException)3 UndefinedParagraphFormatException (org.jabref.logic.openoffice.UndefinedParagraphFormatException)3 XPropertySet (com.sun.star.beans.XPropertySet)2