/* Copyright (C) 2003-2011 JabRef contributors.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package net.sf.jabref.oo;
import com.sun.star.awt.Point;
import com.sun.star.awt.XWindow;
import com.sun.star.beans.XPropertyContainer;
import com.sun.star.beans.XPropertySet;
import com.sun.star.beans.PropertyValue;
import com.sun.star.comp.helper.Bootstrap;
import com.sun.star.container.*;
import com.sun.star.container.NoSuchElementException;
import com.sun.star.document.XDocumentPropertiesSupplier;
import com.sun.star.frame.*;
import com.sun.star.lang.*;
import com.sun.star.lang.Locale;
import com.sun.star.text.*;
import com.sun.star.uno.Any;
import com.sun.star.uno.Type;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.uno.XComponentContext;
import net.sf.jabref.*;
import net.sf.jabref.export.layout.Layout;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Class for manipulating the Bibliography of the currently start document in OpenOffice.
*/
public class OOBibBase {
final static String BIB_SECTION_NAME = "JR_bib";
final static String BIB_SECTION_END_NAME = "JR_bib_end";
final static String BIB_CITATION = "JR_cite";
public final Pattern citePattern = Pattern.compile(BIB_CITATION+"\\d*_(\\d*)_(.*)");
final static int
AUTHORYEAR_PAR = 1,
AUTHORYEAR_INTEXT = 2,
INVISIBLE_CIT = 3;
final static String DEFAULT_CONNECTION_STRING = "uno:socket,host=localhost,port=2002;urp;StarOffice.ServiceManager";
final String[] BIB_TYPES = new String[] { "ARTICLE", "BOOK", "BOOKLET", "CONFERENCE",
"INBOOK", "INCOLLECTION", "INPROCEEDINGS", "JOURNAL", "MANUAL", "MASTERTHESIS",
"MISC", "PHDTHESIS", "PROCEEDINGS", "TECHREPORT", "UNPUBLISHED", "EMAIL", "WWW",
"CUSTOM1", "CUSTOM2", "CUSTOM3", "CUSTOM4", "CUSTOM5" };
private XMultiServiceFactory mxDocFactory = null;
private XTextDocument mxDoc = null;
private XText text = null;
private XDesktop xDesktop = null;
XTextViewCursorSupplier xViewCursorSupplier = null;
XComponent xCurrentComponent = null;
XComponentLoader xComponentLoader = null;
XPropertyContainer userProperties = null;
XPropertySet propertySet = null;
private boolean atEnd;
private AlphanumericComparator entryComparator = new AlphanumericComparator();
private YearComparator yearComparator = new YearComparator();
private HashMap<String,String> uniquefiers = new HashMap<String, String>();
private String[] sortedReferenceMarks = null;
public OOBibBase(String pathToOO, boolean atEnd) throws Exception {
this.atEnd = atEnd;
xDesktop = simpleBootstrap(pathToOO);//getDesktop();
selectDocument();
}
public boolean isConnectedToDocument() {
return xCurrentComponent != null;
}
public String getCurrentDocumentTitle() {
if (mxDoc != null) {
try {
return String.valueOf(OOUtil.getProperty
(mxDoc.getCurrentController().getFrame(), "Title"));
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
else
return null;
}
public void selectDocument() throws Exception {
List<XTextDocument> ls = getTextDocuments();
XTextDocument selected = null;
if (ls.size() == 0) {
// No text documents found.
throw new Exception("No Writer documents found");
}
else if (ls.size() > 1) {
selected = OOUtil.selectComponent(null, xDesktop, ls);
}
else
selected = ls.get(0);
if (selected == null) {
return;
}
xCurrentComponent = (XComponent) UnoRuntime.queryInterface(
XComponent.class, selected);
mxDoc = selected;
com.sun.star.text.XDocumentIndexesSupplier indexesSupp = (com.sun.star.text.XDocumentIndexesSupplier) UnoRuntime.queryInterface(
com.sun.star.text.XDocumentIndexesSupplier.class, xCurrentComponent);
XModel xModel = (XModel) UnoRuntime.queryInterface(XModel.class, xCurrentComponent);
XController xController = xModel.getCurrentController();
xViewCursorSupplier =
(com.sun.star.text.XTextViewCursorSupplier) UnoRuntime.queryInterface(
com.sun.star.text.XTextViewCursorSupplier.class, xController);
// get a reference to the body text of the document
text = mxDoc.getText();
// Access the text document's multi service factory:
mxDocFactory = (XMultiServiceFactory) UnoRuntime.queryInterface(XMultiServiceFactory.class, mxDoc);
XDocumentPropertiesSupplier supp =
UnoRuntime.queryInterface(XDocumentPropertiesSupplier.class, mxDoc);
userProperties = supp.getDocumentProperties().getUserDefinedProperties();
propertySet = UnoRuntime.queryInterface(XPropertySet.class, userProperties);
}
public XDesktop simpleBootstrap(String pathToExecutable) throws Exception {
ClassLoader loader = ClassLoader.getSystemClassLoader();
if (loader instanceof URLClassLoader) {
URLClassLoader cl = (URLClassLoader) loader;
Class sysclass = URLClassLoader.class;
try {
Method method = sysclass.getDeclaredMethod("addURL", new Class[]{URL.class});
method.setAccessible(true);
method.invoke(cl, new Object[]{new File(pathToExecutable).toURI().toURL()});
} catch (Throwable t) {
t.printStackTrace();
throw new IOException("Error, could not add URL to system classloader");
}
} else {
System.out.println("Error occured, URLClassLoader expected but " +
loader.getClass() + " received. Could not continue.");
}
//Get the office component context:
XComponentContext xContext = Bootstrap.bootstrap();
//Get the office service manager:
XMultiComponentFactory xServiceManager = xContext.getServiceManager();
//Create the desktop, which is the root frame of the
//hierarchy of frames that contain viewable components:
Object desktop = xServiceManager.createInstanceWithContext("com.sun.star.frame.Desktop", xContext);
XDesktop xD = (XDesktop) UnoRuntime.queryInterface(XDesktop.class, desktop);
xComponentLoader = (XComponentLoader)UnoRuntime.queryInterface(
XComponentLoader.class, desktop);
return xD;
}
public List<XTextDocument> getTextDocuments() throws Exception {
List<XTextDocument> res = new ArrayList<XTextDocument>();
XEnumerationAccess enumA = xDesktop.getComponents();
XEnumeration e = enumA.createEnumeration();
// TODO: http://api.openoffice.org/docs/DevelopersGuide/OfficeDev/OfficeDev.xhtml#1_1_3_2_1_2_Frame_Hierarchies
while (e.hasMoreElements()) {
Object o = e.nextElement();
XComponent comp = (XComponent) UnoRuntime.queryInterface(XComponent.class, o);
XTextDocument doc = (XTextDocument) UnoRuntime.queryInterface(
XTextDocument.class, comp);
if (doc != null) {
res.add(doc);
}
}
return res;
}
public void testCustomProperties() throws Exception {
XDocumentPropertiesSupplier supp = (XDocumentPropertiesSupplier)UnoRuntime.queryInterface(
XDocumentPropertiesSupplier.class, mxDoc);
XPropertyContainer cont = supp.getDocumentProperties().getUserDefinedProperties();
XPropertySet set = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, cont);
try {
cont.addProperty("JR_cite_1_Danielsen1987", (short)0, new Any(Type.STRING, "Brum"));
} catch (Exception ex) {
System.out.println("property already exists");
}
System.out.println(set.getPropertyValue("Test").toString());
}
public void setCustomProperty(String property, String value) throws Exception {
if (propertySet.getPropertySetInfo().hasPropertyByName(property))
userProperties.removeProperty(property);
if (value != null)
userProperties.addProperty(property, com.sun.star.beans.PropertyAttribute.REMOVEABLE,
new Any(Type.STRING, value));
}
public String getCustomProperty(String property) throws Exception {
if (propertySet.getPropertySetInfo().hasPropertyByName(property))
return propertySet.getPropertyValue(property).toString();
else return null;
}
public void updateSortedReferenceMarks() throws Exception {
XReferenceMarksSupplier supplier = (XReferenceMarksSupplier) UnoRuntime.queryInterface(
XReferenceMarksSupplier.class, xCurrentComponent);
XNameAccess nameAccess = supplier.getReferenceMarks();
String[] names;
sortedReferenceMarks = getSortedReferenceMarks(nameAccess);
}
/**
* This method inserts a cite marker in the text for the given BibtexEntry,
* and may refresh the bibliography.
* @param entries The entries to cite.
* @param database The database the entry belongs to.
* @param style The bibliography style we are using.
* @param inParenthesis Indicates whether it is an in-text citation or a citation in parenthesis.
* This is not relevant if numbered citations are used.
* @param withText Indicates whether this should be a normal citation (true) or an empty
* (invisible) citation (false).
* @param sync Indicates whether the reference list should be refreshed.
* @throws Exception
*/
public void insertEntry(BibtexEntry[] entries, BibtexDatabase database,
List<BibtexDatabase> allBases, OOBibStyle style,
boolean inParenthesis, boolean withText, String pageInfo,
boolean sync) throws Exception {
try {
XTextViewCursor xViewCursor = xViewCursorSupplier.getViewCursor();
if (entries.length > 1) {
if (style.getBooleanCitProperty("MultiCiteChronological"))
Arrays.sort(entries, yearComparator);
else
Arrays.sort(entries, entryComparator);
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < entries.length; i++) {
BibtexEntry entry = entries[i];
if (i > 0)
sb.append(",");
sb.append(entry.getCiteKey());
}
String keyString = sb.toString();
// Insert bookmark:
String bName = getUniqueReferenceMarkName(keyString,
withText ? (inParenthesis ? AUTHORYEAR_PAR : AUTHORYEAR_INTEXT) : INVISIBLE_CIT);
//XTextContent content = insertBookMark(bName, xViewCursor);
// If we should store metadata for page info, do that now:
if (pageInfo != null) {
System.out.println("Storing page info: "+pageInfo);
setCustomProperty(bName, pageInfo);
}
String citeText = style.isNumberEntries() ? "-" : style.getCitationMarker(entries, database, inParenthesis, null, null);
//System.out.println(text+" / "+xViewCursor.getText());
xViewCursor.getText().insertString(xViewCursor, " ", false);
if (style.isFormatCitations()) {
XPropertySet xCursorProps = (XPropertySet) UnoRuntime.queryInterface(
XPropertySet.class, xViewCursor);
String charStyle = style.getCitationCharacterFormat();
try {
xCursorProps.setPropertyValue("CharStyleName", charStyle);
} catch (Throwable ex) {
// Setting the character format failed, so we throw an exception that
// will result in an error message for the user. Before that,
// delete the space we inserted:
xViewCursor.goLeft((short)1,true);
xViewCursor.setString("");
throw new UndefinedCharacterFormatException(charStyle);
}
}
xViewCursor.goLeft((short)1,false);
insertReferenceMark(bName, citeText, xViewCursor, withText, style);
//xViewCursor.collapseToEnd();
xViewCursor.collapseToEnd();
xViewCursor.goRight((short)1,false);
XTextRange position = xViewCursor.getEnd();
if (sync) {
// To account for numbering and for uniqiefiers, we must refresh the cite markers:
updateSortedReferenceMarks();
refreshCiteMarkers(allBases, style);
// Insert it at the current position:
rebuildBibTextSection(allBases, style);
}
// Go back to the relevant position:
try {
xViewCursor.gotoRange(position, false);
} catch (Exception ex) {
System.out.println("Catch");
ex.printStackTrace();
}
} catch (DisposedException ex) {
// We need to catch this one here because the OpenOfficePanel class is
// loaded before connection, and therefore cannot directly reference
// or catch a DisposedException (which is in a OO jar file).
throw new ConnectionLostException(ex.getMessage());
}
}
/**
* Refresh all cite markers in the document.
* @param databases The databases to get entries from.
* @param style The bibliography style to use.
* @return A list of those referenced BibTeX keys that could not be resolved.
* @throws Exception
*/
public List<String> refreshCiteMarkers(List<BibtexDatabase> databases, OOBibStyle style) throws
Exception {
try {
return refreshCiteMarkersInternal(databases, style);
} catch (DisposedException ex) {
// We need to catch this one here because the OpenOfficePanel class is
// loaded before connection, and therefore cannot directly reference
// or catch a DisposedException (which is in a OO jar file).
throw new ConnectionLostException(ex.getMessage());
}
}
public XNameAccess getReferenceMarks() {
XReferenceMarksSupplier supplier = (XReferenceMarksSupplier) UnoRuntime.queryInterface(
XReferenceMarksSupplier.class, xCurrentComponent);
return supplier.getReferenceMarks();
}
public String[] getJabRefReferenceMarks(XNameAccess nameAccess) {
String[] names = nameAccess.getElementNames();
// Remove all reference marks that don't look like JabRef citations:
ArrayList<String> tmp = new ArrayList<String>();
for (int i = 0; i < names.length; i++) {
if (citePattern.matcher(names[i]).find())
tmp.add(names[i]);
}
names = tmp.toArray(new String[tmp.size()]);
return names;
}
private List<String> refreshCiteMarkersInternal(List<BibtexDatabase> databases, OOBibStyle style) throws
Exception {
List<String> cited = findCitedKeys();
HashMap<String,BibtexDatabase> linkSourceBase = new HashMap<String, BibtexDatabase>();
Map<BibtexEntry,BibtexDatabase> entries = findCitedEntries(databases, cited, linkSourceBase);
XNameAccess nameAccess = getReferenceMarks();
String[] names;
if (style.isSortByPosition()) {
// We need to sort the reference marks according to their order of appearance:
/*if (sortedReferenceMarks == null)
updateSortedReferenceMarks();*/
names = sortedReferenceMarks;
}
else if (style.isNumberEntries()) {
// We need to sort the reference marks according to the sorting of the bibliographic
// entries:
SortedMap<BibtexEntry,BibtexDatabase> newMap =
new TreeMap<BibtexEntry, BibtexDatabase>(entryComparator);
for (BibtexEntry entry : entries.keySet())
newMap.put(entry, entries.get(entry));
entries = newMap;
// Rebuild the list of cited keys according to the sort order:
cited.clear();
for (Iterator<BibtexEntry> iterator = entries.keySet().iterator(); iterator.hasNext();) {
BibtexEntry entry = iterator.next();
cited.add(entry.getCiteKey());
}
names = nameAccess.getElementNames();
}
else {
/*if (sortedReferenceMarks == null)
updateSortedReferenceMarks();*/
names = sortedReferenceMarks;
}
// Remove all reference marks that don't look like JabRef citations:
ArrayList<String> tmp = new ArrayList<String>();
for (int i = 0; i < names.length; i++) {
if (citePattern.matcher(names[i]).find())
tmp.add(names[i]);
}
names = tmp.toArray(new String[tmp.size()]);
HashMap<String,Integer> numbers = new HashMap<String, Integer>();
//HashMap<S
int lastNum = 0;
// First compute citation markers for all citations:
String[] citMarkers = new String[names.length];
String[][] normCitMarkers = new String[names.length][];
String[][] bibtexKeys = new String[names.length][];
int minGroupingCount = style.getIntCitProperty("MinimumGroupingCount");
int[] types = new int[names.length];
for (int i = 0; i < names.length; i++) {
Matcher m = citePattern.matcher(names[i]);
if (m.find()) {
String typeStr = m.group(1);
int type = Integer.parseInt(typeStr);
types[i] = type; // Remember the type in case we need to uniqiefy.
String[] keys = m.group(2).split(",");
bibtexKeys[i] = keys;
BibtexEntry[] cEntries = new BibtexEntry[keys.length];
for (int j = 0; j < cEntries.length; j++) {
BibtexDatabase database = linkSourceBase.get(keys[j]);
cEntries[j] = null;
if (database != null)
cEntries[j] = OOUtil.createAdaptedEntry(database.getEntryByKey(keys[j]));
if (cEntries[j] == null) {
System.out.println("Bibtex key not found : '"+keys[j]+"'");
System.out.println("Problem with reference mark: '"+names[i]+"'");
cEntries[j] = new UndefinedBibtexEntry(keys[j]);
//throw new BibtexEntryNotFoundException(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].getCiteKey();
sb.append(cEntries[j].getCiteKey());
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:
int[] num = new int[keys.length];
for (int j=0; j<keys.length; j++) {
if (cEntries[j] instanceof UndefinedBibtexEntry) {
num[j] = -1;
} else {
num[j] = lastNum + 1;
if (numbers.containsKey(keys[j]))
num[j] = numbers.get(keys[j]);
else {
numbers.put(keys[j], num[j]);
lastNum = num[j];
}
}
}
citationMarker = style.getNumCitationMarker(num, minGroupingCount, false);
for (int j=0; j<keys.length; j++)
normCitMarker[j] = style.getNumCitationMarker(new int[] {num[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:
int[] num = findCitedEntryIndex(names[i], cited);
if (num != null)
citationMarker = style.getNumCitationMarker(num, minGroupingCount, false);
else
throw new BibtexEntryNotFoundException(names[i], Globals.lang("Could not resolve BibTeX entry for citation marker '%0'.", names[i]));
for (int j=0; j<keys.length; j++)
normCitMarker[j] = style.getNumCitationMarker(new int[] {num[j]},
minGroupingCount, false);
}
}
else {
if (cEntries.length > 1) {
if (style.getBooleanCitProperty("MultiCiteChronological"))
Arrays.sort(cEntries, yearComparator);
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].getCiteKey();
}
}
/*System.out.println(style.getBooleanCitProperty("MultiCiteChronological"));
for (int j = 0; j < cEntries.length; j++) {
BibtexEntry cEntry = cEntries[j];
System.out.println(cEntry.getCiteKey());
} */
citationMarker = style.getCitationMarker(cEntries, entries.get(cEntries), type == 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(cEntries[j], entries.get(cEntries), true, null, -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:
HashMap<String,List<String>> refKeys = new HashMap<String, List<String>>();
HashMap<String,List<Integer>> refNums = new HashMap<String, List<Integer>>();
for (int i = 0; i < citMarkers.length; i++) {
String[] markers = normCitMarkers[i]; // compare normalized markers, since the actual markers can be different
for (int j=0; j<markers.length; j++) {
String marker = markers[j];
if (!refKeys.containsKey(marker)) {
List<String> l = new ArrayList<String>(1);
l.add(bibtexKeys[i][j]);
refKeys.put(marker, l);
List<Integer> l2 = new ArrayList<Integer>(1);
l2.add(i);
refNums.put(marker, l2);
}
else {
// Ok, we have seen this exact marker before.
if (!refKeys.get(marker).contains(bibtexKeys[i][j])) {
// ... but not for this entry.
refKeys.get(marker).add(bibtexKeys[i][j]);
refNums.get(marker).add(i);
}
}
}
}
// Go through the collected lists and see where we need to uniquefy:
for (String marker : refKeys.keySet()) {
List<String> keys = refKeys.get(marker);
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("MaxAuthorsFirst");
HashSet<String> seenBefore = new HashSet<String>();
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];
BibtexEntry[] cEntries = new BibtexEntry[bibtexKeys[j].length];
for (int k=0; k<bibtexKeys[j].length; k++) {
firstLimAuthors[k] = -1;
if (maxAuthorsFirst > 0) {
if (!seenBefore.contains(bibtexKeys[j][k])) {
firstLimAuthors[k] = maxAuthorsFirst;
}
seenBefore.add(bibtexKeys[j][k]);
}
String uniq = uniquefiers.get(bibtexKeys[j][k]);
if ((uniq != null) && (uniq.length() >= 0)) {
needsChange = true;
BibtexDatabase database = linkSourceBase.get(bibtexKeys[j][k]);
if (database != null)
cEntries[k] = OOUtil.createAdaptedEntry(database.getEntryByKey(bibtexKeys[j][k]));
uniquif[k] = uniq;
}
else if (firstLimAuthors[k] > 0) {
needsChange = true;
BibtexDatabase database = linkSourceBase.get(bibtexKeys[j][k]);
if (database != null)
cEntries[k] = OOUtil.createAdaptedEntry(database.getEntryByKey(bibtexKeys[j][k]));
uniquif[k] = "";
}
else {
BibtexDatabase database = linkSourceBase.get(bibtexKeys[j][k]);
if (database != null)
cEntries[k] = OOUtil.createAdaptedEntry(database.getEntryByKey(bibtexKeys[j][k]));
uniquif[k] = "";
}
}
if (needsChange) {
citMarkers[j] = style.getCitationMarker(cEntries, entries.get(cEntries), types[j] == AUTHORYEAR_PAR,
uniquif, firstLimAuthors);
}
}
}
// Refresh all reference marks with the citation markers we computed:
boolean hadBibSection = getBookmarkRange(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.length; i++) {
Object o = nameAccess.getByName(names[i]);
XTextContent bm = (XTextContent) UnoRuntime.queryInterface
(XTextContent.class, o);
XTextCursor cursor = bm.getAnchor().getText().createTextCursorByRange(bm.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.
mustTestCharFormat = false; // need to do this only once
XPropertySet xCursorProps = (XPropertySet) UnoRuntime.queryInterface(
XPropertySet.class, cursor);
String charStyle = style.getCitationCharacterFormat();
try {
xCursorProps.setPropertyValue("CharStyleName", charStyle);
} catch (Throwable ex) {
throw new UndefinedCharacterFormatException(charStyle);
}
}
text.removeTextContent(bm);
insertReferenceMark(names[i], citMarkers[i], cursor, types[i] != INVISIBLE_CIT, style);
if (hadBibSection && (getBookmarkRange(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(BIB_SECTION_NAME, cursor);
/* The following is for resetting the paragraph format, but should probably
not be done.
XParagraphCursor parCursor =
(XParagraphCursor)UnoRuntime.queryInterface(
java.lang.Class.forName("com.sun.star.text.XParagraphCursor"), cursor);
parCursor.gotoPreviousParagraph(false);
parCursor.gotoStartOfParagraph(false);
parCursor.gotoEndOfParagraph(true);
XPropertySet props = (XPropertySet) UnoRuntime.queryInterface(
XPropertySet.class, parCursor);
try {
props.setPropertyValue("ParaStyleName", "Default");
} catch (com.sun.star.lang.IllegalArgumentException ex) {
throw new UndefinedParagraphFormatException("Default");
}
*/
}
}
ArrayList<String> unresolvedKeys = new ArrayList<String>();
for (BibtexEntry entry : entries.keySet()) {
if (entry instanceof UndefinedBibtexEntry) {
String key = ((UndefinedBibtexEntry)entry).getKey();
if (!unresolvedKeys.contains(key))
unresolvedKeys.add(key);
}
}
return unresolvedKeys;
}
public String[] getSortedReferenceMarks(final XNameAccess nameAccess) throws Exception {
/*
PropertyValue[] props = new PropertyValue[2];
props[0] = new PropertyValue();
props[0].Name = "Model";
props[0].Value = mxDoc.getCurrentController().getModel();
props[1] = new PropertyValue();
props[1].Name = "Hidden";
props[1].Value = true;
// argument xModel wins over URL.
System.out.println("her");
XComponent comp = xComponentLoader.loadComponentFromURL("private:factory/swriter",
"_blank", 0, props);
System.out.println("her2");
XTextDocument newDoc = (XTextDocument)UnoRuntime.queryInterface(
XTextDocument.class, comp);
System.out.println("newDoc = "+newDoc);
// Controller of the hidden frame
XController xController = newDoc.getCurrentController();
XFrame xFrame = xController.getFrame();
XWindow xContainerWindow = xFrame.getContainerWindow();
XWindow xComponentWindow = xFrame.getComponentWindow();
xContainerWindow.setVisible(true);
xComponentWindow.setFocus();
xContainerWindow.setVisible(false);
*/
XTextViewCursorSupplier css = (XTextViewCursorSupplier)UnoRuntime.queryInterface(
XTextViewCursorSupplier.class, mxDoc.getCurrentController());
XTextViewCursor tvc = css.getViewCursor();
XTextRange initialPos = tvc.getStart();
String[] names = nameAccess.getElementNames();
Point[] positions = new Point[names.length];
for (int i = 0; i < names.length; i++) {
String name = names[i];
XTextContent tc = (XTextContent) UnoRuntime.queryInterface
(XTextContent.class, nameAccess.getByName(name));
XTextRange r = tc.getAnchor();
// Check if we are inside a footnote:
if (UnoRuntime.queryInterface(XFootnote.class, r.getText()) != null) {
// Find the linking footnote marker:
XFootnote footer = (XFootnote)UnoRuntime.queryInterface(XFootnote.class, r.getText());
// The footnote's anchor gives the correct position in the text:
r = footer.getAnchor();
}
positions[i] = findPosition(tvc, r);
}
TreeSet<ComparableMark> set = new TreeSet<ComparableMark>();
for (int i = 0; i < positions.length; i++) {
set.add(new ComparableMark(names[i], positions[i]));
}
int i=0;
for (Iterator<ComparableMark> iterator = set.iterator(); iterator.hasNext();) {
ComparableMark mark = iterator.next();
//System.out.println(mark.getPosition().X+" -- "+mark.getPosition().Y+" : "+mark.getName());
names[i++] = mark.getName();
}
tvc.gotoRange(initialPos, false);
//xFrame.dispose();
return names;
/*final XTextRangeCompare compare = (XTextRangeCompare) UnoRuntime.queryInterface
(XTextRangeCompare.class, text);
Arrays.sort(names, new Comparator<String>() {
public int compare(String o1, String o2) {
try {
XTextRange r1 = ((XTextContent) UnoRuntime.queryInterface
(XTextContent.class, nameAccess.getByName(o1))).getAnchor();
XTextRange r2 = ((XTextContent) UnoRuntime.queryInterface
(XTextContent.class, nameAccess.getByName(o2))).getAnchor();
try {
return compare.compareRegionStarts(r2, r1);
} catch (com.sun.star.lang.IllegalArgumentException ex) {
// problem comparing reference marks in different areas (text, table, etc.)
return 0;
}
} catch (Exception ex) {
ex.printStackTrace();
return 0;
}
}
});
return names;*/
}
public void rebuildBibTextSection(List<BibtexDatabase> databases, OOBibStyle style)
throws Exception {
List<String> cited = findCitedKeys();
HashMap<String,BibtexDatabase> linkSourceBase = new HashMap<String, BibtexDatabase>();
Map<BibtexEntry,BibtexDatabase> entries = findCitedEntries
(databases, cited, linkSourceBase);
String[] names = sortedReferenceMarks;
if (style.isSortByPosition()) {
// We need to sort the entries according to their order of appearance:
entries = getSortedEntriesFromSortedRefMarks(names, entries, linkSourceBase);
}
else {
SortedMap<BibtexEntry,BibtexDatabase> newMap =
new TreeMap<BibtexEntry, BibtexDatabase>(entryComparator);
for (BibtexEntry entry : entries.keySet())
newMap.put(entry, entries.get(entry));
entries = newMap;
}
clearBibTextSectionContent2();
populateBibTextSection(entries, style);
}
public String getUniqueReferenceMarkName(String bibtexKey, int type) {
XReferenceMarksSupplier supplier = (XReferenceMarksSupplier) UnoRuntime.queryInterface(
XReferenceMarksSupplier.class, xCurrentComponent);
XNameAccess xNamedRefMarks = supplier.getReferenceMarks();
int i=0;
String name = BIB_CITATION+"_"+type+"_"+bibtexKey;
while (xNamedRefMarks.hasByName(name)) {
name = BIB_CITATION+i+"_"+type+"_"+bibtexKey;
i++;
}
return name;
}
public LinkedHashMap<BibtexEntry,BibtexDatabase> findCitedEntries
(List<BibtexDatabase> databases, List<String> keys,
HashMap<String,BibtexDatabase> linkSourceBase) {
LinkedHashMap<BibtexEntry,BibtexDatabase> entries = new LinkedHashMap<BibtexEntry, BibtexDatabase>();
for (String key : keys) {
boolean found = false;
bases: for (BibtexDatabase database : databases) {
BibtexEntry entry = database.getEntryByKey(key);
if (entry != null) {
entries.put(OOUtil.createAdaptedEntry(entry), database);
linkSourceBase.put(key, database);
found = true;
break bases;
}
}
if (!found)
entries.put(new UndefinedBibtexEntry(key), null);
}
return entries;
}
public List<String> findCitedKeys() throws com.sun.star.container.NoSuchElementException, WrappedTargetException {
XReferenceMarksSupplier supplier = (XReferenceMarksSupplier) UnoRuntime.queryInterface(
XReferenceMarksSupplier.class, xCurrentComponent);
XNameAccess xNamedMarks = supplier.getReferenceMarks();
String[] names = xNamedMarks.getElementNames();
ArrayList<String> keys = new ArrayList<String>();
for (int i = 0; i < names.length; i++) {
Object bookmark = xNamedMarks.getByName(names[i]);
XTextContent xTextContent = (XTextContent) UnoRuntime.queryInterface(
XTextContent.class, bookmark);
String name = names[i];
List<String> newKeys = parseRefMarkName(name);
for (String key : newKeys)
if (!keys.contains(key))
keys.add(key);
}
return keys;
}
public LinkedHashMap<BibtexEntry,BibtexDatabase> getSortedEntriesFromSortedRefMarks
(String[] names,
Map<BibtexEntry,BibtexDatabase> entries,
HashMap<String,BibtexDatabase> linkSourceBase)
throws BibtexEntryNotFoundException {
LinkedHashMap<BibtexEntry,BibtexDatabase> newList = new LinkedHashMap<BibtexEntry,BibtexDatabase>();
HashMap<BibtexEntry,BibtexEntry> adaptedEntries = new HashMap<BibtexEntry,BibtexEntry>();
for (int i = 0; i < names.length; i++) {
Matcher m = citePattern.matcher(names[i]);
if (m.find()) {
String[] keys = m.group(2).split(",");
for (int j = 0; j < keys.length; j++) {
BibtexDatabase database = linkSourceBase.get(keys[j]);
BibtexEntry origEntry = null;
if (database != null) origEntry = database.getEntryByKey(keys[j]);
if (origEntry == null) {
System.out.println("Bibtex key not found : '"+keys[j]+"'");
System.out.println("Problem with reference mark: '"+names[i]+"'");
newList.put(new UndefinedBibtexEntry(keys[j]), null);
//throw new BibtexEntryNotFoundException(keys[j], "");
} else {
BibtexEntry entry = adaptedEntries.get(origEntry);
if (entry == null) {
entry = OOUtil.createAdaptedEntry(origEntry);
adaptedEntries.put(origEntry, entry);
}
if (!newList.containsKey(entry)) {
newList.put(entry, database);
}
}
}
}
}
return newList;
}
public Point findPosition(XTextViewCursor cursor, XTextRange range) {
cursor.gotoRange(range, false);
return cursor.getPosition();
}
/**
* Extract the list of bibtex keys from a reference mark name.
* @param name The reference mark name.
* @return The list of bibtex keys encoded in the name.
*/
public List<String> parseRefMarkName(String name) {
ArrayList<String> keys = new ArrayList<String>();
Matcher m = citePattern.matcher(name);
if (m.find()) {
String[] keystring = m.group(2).split(",");
for (int j = 0; j < keystring.length; j++) {
if (!keys.contains(keystring[j]))
keys.add(keystring[j]);
}
}
return keys;
}
/**
* Resolve the bibtex key from a citation reference marker name, and look up
* the index of the key in a list of keys.
* @param citRefName The name of the ReferenceMark representing the citation.
* @param keys A List of bibtex keys representing the entries in the bibliography.
* @return the indices of the cited keys, -1 if a key is not found. Returns null if the ref name
* could not be resolved as a citation.
*/
public int[] findCitedEntryIndex(String citRefName, List<String> keys) {
Matcher m = citePattern.matcher(citRefName);
if (m.find()) {
String[] keyStrings = m.group(2).split(",");
int[] res = new int[keyStrings.length];
for (int i=0; i<keyStrings.length; i++) {
int ind = keys.indexOf(keyStrings[i]);
res[i] = ind != -1 ? 1+ind : -1;
}
return res;
}
else
return null;
}
public String getCitationContext(XNameAccess nameAccess, String refMarkName,
int charBefore, int charAfter,
boolean htmlMarkup) throws Exception {
Object o = nameAccess.getByName(refMarkName);
XTextContent bm = (XTextContent) UnoRuntime.queryInterface
(XTextContent.class, o);
XTextCursor cursor = bm.getAnchor().getText().createTextCursorByRange(bm.getAnchor());
String citPart = cursor.getString();
int flex = 8;
for (int i=0; i<charBefore; i++) {
try {
cursor.goLeft((short)1, true);
if ((i >= charBefore-flex) && Character.isWhitespace(cursor.getString().charAt(0)))
break;
} catch (Exception ex) {
ex.printStackTrace();
}
}
int length = cursor.getString().length();
int added = length - citPart.length();
cursor.collapseToStart();
for (int i=0; i<charAfter+length; i++) {
try {
cursor.goRight((short)1, true);
if (i >= charAfter+length-flex) {
String strNow = cursor.getString();
if (Character.isWhitespace(strNow.charAt(strNow.length()-1)))
break;
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
String result = cursor.getString();
if (htmlMarkup) {
result = result.substring(0, added)+"<b>"+citPart+
"</b>"+result.substring(length);
}
return result.trim();
}
public void insertFullReferenceAtCursor(XTextCursor cursor, Map<BibtexEntry,BibtexDatabase> entries,
OOBibStyle style, String parFormat)
throws UndefinedParagraphFormatException, Exception {
// If we don't have numbered entries, we need to sort the entries before adding them:
if (!style.isSortByPosition()) {
Map<BibtexEntry,BibtexDatabase> newMap = new TreeMap<BibtexEntry,BibtexDatabase>(entryComparator);
for (BibtexEntry entry : entries.keySet())
newMap.put(entry, entries.get(entry));
entries = newMap;
}
int number = 1;
for (BibtexEntry entry : entries.keySet()) {
if (entry instanceof UndefinedBibtexEntry)
continue;
OOUtil.insertParagraphBreak(text, cursor);
if (style.isNumberEntries()) {
int minGroupingCount = style.getIntCitProperty("MinimumGroupingCount");
OOUtil.insertTextAtCurrentLocation(text, cursor,
style.getNumCitationMarker(new int[] {number++}, minGroupingCount, true),
false, false, false, false, false, false);
}
Layout layout = style.getReferenceFormat(entry.getType().getName());
try {
layout.setPostFormatter(OOUtil.postformatter);
} catch (NoSuchMethodError ex) {
}
OOUtil.insertFullReferenceAtCurrentLocation(text, cursor, layout, parFormat, entry,
entries.get(entry), uniquefiers.get(entry.getCiteKey()));
}
}
public void insertFullReferenceAtViewCursor(Map<BibtexEntry,BibtexDatabase> entries,
OOBibStyle style, String parFormat) throws Exception {
XTextViewCursor xViewCursor = xViewCursorSupplier.getViewCursor();
insertFullReferenceAtCursor(xViewCursor, entries, style, parFormat);
}
public void insertMarkedUpTextAtViewCursor(String lText, String parFormat) throws Exception {
XTextViewCursor xViewCursor = xViewCursorSupplier.getViewCursor();
XTextCursor cursor = text.createTextCursorByRange(xViewCursor.getEnd());
OOUtil.insertOOFormattedTextAtCurrentLocation(text,cursor, lText, parFormat);
}
/**
* This method creates and inserts an XTextSection named as determined by the
* string BIB_SECTION_NAME.
* @param end true to indicate that the section should be put at the end of the document,
* false to indicate that it should be put at the cursor position.
* @return true if the bibliography already existed, false otherwise..
* @throws Exception
*/
public boolean createBibTextSection(boolean end) throws Exception {
// Check if there already is a bookmarked section:
XBookmarksSupplier bSupp = (XBookmarksSupplier) UnoRuntime.queryInterface(
XBookmarksSupplier.class, mxDoc);
if (bSupp.getBookmarks().hasByName(BIB_SECTION_NAME)) {
System.out.println("Found existing JabRef bookmark");
return true;
}
XTextCursor mxDocCursor = text.createTextCursor();
if (end)
mxDocCursor.gotoEnd(false);
OOUtil.insertParagraphBreak(text, mxDocCursor);
insertBookMark(BIB_SECTION_NAME, mxDocCursor);
return false;
}
public void createBibTextSection2(boolean end) throws Exception {
XTextCursor mxDocCursor = text.createTextCursor();
if (end)
mxDocCursor.gotoEnd(false);
OOUtil.insertParagraphBreak(text, mxDocCursor);
// Create a new TextSection from the document factory and access it's XNamed interface
XNamed xChildNamed = UnoRuntime.queryInterface(
XNamed.class, mxDocFactory.createInstance("com.sun.star.text.TextSection"));
// Set the new sections name to 'Child_Section'
xChildNamed.setName(BIB_SECTION_NAME);
// Access the Child_Section's XTextContent interface and insert it into the document
XTextContent xChildSection = (XTextContent) UnoRuntime.queryInterface(
XTextContent.class, xChildNamed);
text.insertTextContent (mxDocCursor, xChildSection, false);
}
public void clearBibTextSectionContent2() throws Exception {
// Check if the section exists:
boolean exists = false;
XTextSectionsSupplier supp = UnoRuntime.queryInterface(
XTextSectionsSupplier.class, mxDoc);
try {
XTextSection section = (XTextSection)((Any)supp.getTextSections().getByName(BIB_SECTION_NAME)).getObject();
// Clear it:
XTextCursor cursor = text.createTextCursorByRange(section.getAnchor());
cursor.gotoRange(section.getAnchor(), false);
cursor.setString("");
} catch (NoSuchElementException ex) {
createBibTextSection2(atEnd);
}
}
public void clearBibTextSectionContent() throws Exception {
// Get a range comparator:
XTextRangeCompare compare = (XTextRangeCompare) UnoRuntime.queryInterface
(XTextRangeCompare.class, text);
// Find the bookmarks for the bibliography:
XTextRange range = getBookmarkRange(BIB_SECTION_NAME);
if (range == null) {
createBibTextSection(atEnd);
}
XTextRange rangeEnd = getBookmarkRange(BIB_SECTION_END_NAME);
if (rangeEnd == null) {
// No end bookmark. This means that there is no bibliography.
return;
}
// Get a paragraph cursor at the start of the bibliography:
//System.out.println("text="+text+" range="+range);
XTextCursor mxDocCursor = text.createTextCursorByRange(range.getEnd());
mxDocCursor.goRight((short)1, true);
boolean couldExpand = true;
while (couldExpand && (compare.compareRegionEnds(mxDocCursor, rangeEnd) > 0)) {
couldExpand = mxDocCursor.goRight((short)1, true);
}
// Finally, clear the bibliography:
mxDocCursor.setString("");
mxDocCursor.collapseToStart();
removeBookMark(BIB_SECTION_END_NAME);
// If we lost the start bookmark, recreate it:
if (getBookmarkRange(BIB_SECTION_NAME) == null)
insertBookMark(BIB_SECTION_NAME, mxDocCursor);
}
public void populateBibTextSection(Map<BibtexEntry,BibtexDatabase> entries,
OOBibStyle style)
throws UndefinedParagraphFormatException, Exception {
XTextSectionsSupplier supp = UnoRuntime.queryInterface(XTextSectionsSupplier.class, mxDoc);
XTextSection section = (XTextSection)((Any)supp.getTextSections().getByName(BIB_SECTION_NAME))
.getObject();
XTextCursor cursor = text.createTextCursorByRange(section.getAnchor());
OOUtil.insertTextAtCurrentLocation(text, cursor, (String)style.getProperty("Title"),
(String)style.getProperty("ReferenceHeaderParagraphFormat"));
insertFullReferenceAtCursor(cursor, entries, style,
(String)style.getProperty("ReferenceParagraphFormat"));
insertBookMark(BIB_SECTION_END_NAME, cursor);
}
public XTextContent insertBookMark(String name, XTextCursor position) throws Exception {
Object bookmark = mxDocFactory.createInstance("com.sun.star.text.Bookmark");
// name the bookmark
XNamed xNamed = (XNamed) UnoRuntime.queryInterface(
XNamed.class, bookmark);
xNamed.setName(name);
// get XTextContent interface
XTextContent xTextContent = (XTextContent) UnoRuntime.queryInterface(
XTextContent.class, bookmark);
// insert bookmark at the end of the document
// instead of mxDocText.getEnd you could use a text cursor's XTextRange interface or any XTextRange
text.insertTextContent(position, xTextContent, true);
position.collapseToEnd();
return xTextContent;
}
public void insertReferenceMark(String name, String citText, XTextCursor position, boolean withText,
OOBibStyle style)
throws Exception {
// Check if there is "page info" stored for this citation. If so, insert it into
// the citation text before inserting the citation:
String pageInfo = getCustomProperty(name);
if (pageInfo != null) {
citText = style.insertPageInfo(citText, pageInfo);
}
Object bookmark = mxDocFactory.createInstance("com.sun.star.text.ReferenceMark");
// Name the reference
XNamed xNamed = UnoRuntime.queryInterface(XNamed.class, bookmark);
xNamed.setName(name);
// get XTextContent interface
if (true) {
XTextContent xTextContent = UnoRuntime.queryInterface(XTextContent.class, bookmark);
if (withText) {
position.setString(citText);
XPropertySet xCursorProps = UnoRuntime.queryInterface(XPropertySet.class, position);
// Set language to [None]:
xCursorProps.setPropertyValue("CharLocale", new Locale("zxx", "", ""));
if (style.isFormatCitations()) {
String charStyle = style.getCitationCharacterFormat();
try {
xCursorProps.setPropertyValue("CharStyleName", charStyle);
} catch (Throwable ex) {
throw new UndefinedCharacterFormatException(charStyle);
}
}
}
else
position.setString("");
position.getText().insertTextContent(position, xTextContent, true);
// Check if we should italicize the "et al." string in citations:
boolean italicize = style.getBooleanCitProperty("ItalicEtAl");
if (italicize) {
String etAlString = style.getStringCitProperty("EtAlString");
int index = citText.indexOf(etAlString);
if (index >= 0) {
italicizeOrBold(position, true, index, index+etAlString.length());
}
}
}
position.collapseToEnd();
}
private void italicizeOrBold(XTextCursor position, boolean italicize,
int start, int end) throws Exception {
XTextRange rng = position.getStart();
XTextCursor cursor = position.getText().createTextCursorByRange(rng);
cursor.goRight((short)start, false);
cursor.goRight((short)(end-start), true);
XPropertySet xcp = UnoRuntime.queryInterface(XPropertySet.class, cursor);
if (italicize)
xcp.setPropertyValue("CharPosture", com.sun.star.awt.FontSlant.ITALIC);
else
xcp.setPropertyValue("CharWeight", com.sun.star.awt.FontWeight.BOLD);
}
public void testFootnote() throws Exception {
XTextViewCursor xViewCursor = xViewCursorSupplier.getViewCursor();
insertFootnote("jabbes", "Cite text", xViewCursor);
}
public void insertFootnote(String name, String citText, XTextCursor position) throws Exception {
XFootnote xFootnote = (XFootnote) UnoRuntime.queryInterface( XFootnote.class,
mxDocFactory.createInstance("com.sun.star.text.Footnote"));
xFootnote.setLabel("");
XPropertySet props = (XPropertySet)UnoRuntime.queryInterface(XPropertySet.class, xFootnote);
props.setPropertyValue("ReferenceId", name); // doesn't work: short data type
System.out.println(props.getPropertyValue("ReferenceId"));
XTextContent xContent = (XTextContent)UnoRuntime.queryInterface(
XTextContent.class, xFootnote);
text.insertTextContent (position, xContent, false);
XSimpleText xSimple = (XSimpleText)UnoRuntime.queryInterface(XSimpleText.class, xFootnote);
XTextRange xRange = (XTextRange)UnoRuntime.queryInterface(XTextRange.class, xSimple.createTextCursor());
xSimple.insertString (xRange, citText, false);
}
public void removeBookMark(String name) throws Exception {
XBookmarksSupplier xBookmarksSupplier = (XBookmarksSupplier) UnoRuntime.queryInterface(
XBookmarksSupplier.class, xCurrentComponent);
if (xBookmarksSupplier.getBookmarks().hasByName(name)) {
Object o = xBookmarksSupplier.getBookmarks().getByName(name);
XTextContent bm = (XTextContent) UnoRuntime.queryInterface(
XTextContent.class, o);
text.removeTextContent(bm);
}
}
public void removeReferenceMark(String name) throws Exception {
XReferenceMarksSupplier xSupplier = (XReferenceMarksSupplier) UnoRuntime.queryInterface(
XReferenceMarksSupplier.class, xCurrentComponent);
if (xSupplier.getReferenceMarks().hasByName(name)) {
Object o = xSupplier.getReferenceMarks().getByName(name);
XTextContent bm = (XTextContent) UnoRuntime.queryInterface(
XTextContent.class, o);
text.removeTextContent(bm);
}
}
/**
* Get the XTextRange corresponding to the named bookmark.
* @param name The name of the bookmark to find.
* @return The XTextRange for the bookmark.
* @throws Exception
*/
public XTextRange getBookmarkRange(String name) throws Exception {
// query XBookmarksSupplier from document model and get bookmarks collection
XBookmarksSupplier xBookmarksSupplier = (XBookmarksSupplier) UnoRuntime.queryInterface(
XBookmarksSupplier.class, xCurrentComponent);
XNameAccess xNamedBookmarks = xBookmarksSupplier.getBookmarks();
// retrieve bookmark by name
//System.out.println("Name="+name+" : "+xNamedBookmarks.hasByName(name));
if (!xNamedBookmarks.hasByName(name))
return null;
Object foundBookmark = xNamedBookmarks.getByName(name);
XTextContent xFoundBookmark = (XTextContent) UnoRuntime.queryInterface(
XTextContent.class, foundBookmark);
return xFoundBookmark.getAnchor();
}
public void printBookmarkNames() throws Exception {
XBookmarksSupplier xBookmarksSupplier = (XBookmarksSupplier) UnoRuntime.queryInterface(
XBookmarksSupplier.class, xCurrentComponent);
XNameAccess xNamedBookmarks = xBookmarksSupplier.getBookmarks();
String[] names = xNamedBookmarks.getElementNames();
for (int i = 0; i < names.length; i++) {
System.out.println(i+". "+names[i]);
}
}
/**
* Focus the active OO document.
*/
public void setFocus() {
xDesktop.getCurrentFrame().getContainerWindow().setFocus();
}
public void combineCiteMarkers(List<BibtexDatabase> databases, OOBibStyle style) throws Exception {
XReferenceMarksSupplier supplier = (XReferenceMarksSupplier) UnoRuntime.queryInterface(
XReferenceMarksSupplier.class, xCurrentComponent);
XNameAccess nameAccess = supplier.getReferenceMarks();
// TODO: doesn't work for citations in footnotes/tables
String[] names = getSortedReferenceMarks(nameAccess);
final XTextRangeCompare compare = (XTextRangeCompare) UnoRuntime.queryInterface
(XTextRangeCompare.class, text);
int piv = 0;
boolean madeModifications = false;
while (piv < names.length-1) {
XTextRange r1 = ((XTextContent) UnoRuntime.queryInterface
(XTextContent.class, nameAccess.getByName(names[piv]))).getAnchor().getEnd();
XTextRange r2 = ((XTextContent) UnoRuntime.queryInterface
(XTextContent.class,
nameAccess.getByName(names[piv+1]))).getAnchor().getStart();
if (r1.getText() != r2.getText()) {
piv++;
continue;
}
XTextCursor mxDocCursor = r1.getText().createTextCursorByRange(r1);
mxDocCursor.goRight((short)1, true);
boolean couldExpand = true;
while (couldExpand && (compare.compareRegionEnds(mxDocCursor, r2) > 0)) {
couldExpand = mxDocCursor.goRight((short)1, true);
}
String text = mxDocCursor.getString();
// Check if the string contains no line breaks and only whitespace:
if ((text.indexOf('\n') == -1) && (text.trim().length() == 0)) {
// If we are supposed to set character format for citations, test this before
// making any changes. This way we can throw an exception before any reference
// marks are removed, preventing damage to the user's document:
if (style.isFormatCitations()) {
XPropertySet xCursorProps = (XPropertySet) UnoRuntime.queryInterface(
XPropertySet.class, mxDocCursor);
String charStyle = style.getCitationCharacterFormat();
try {
xCursorProps.setPropertyValue("CharStyleName", charStyle);
} catch (Throwable ex) {
// Setting the character format failed, so we throw an exception that
// will result in an error message for the user:
throw new UndefinedCharacterFormatException(charStyle);
}
}
List<String> keys = parseRefMarkName(names[piv]);
keys.addAll(parseRefMarkName(names[piv+1]));
removeReferenceMark(names[piv]);
removeReferenceMark(names[piv+1]);
ArrayList<BibtexEntry> entries = new ArrayList<BibtexEntry>();
for (String key : keys) {
bases: for (BibtexDatabase database : databases) {
BibtexEntry entry = database.getEntryByKey(key);
if (entry != null) {
entries.add(OOUtil.createAdaptedEntry(entry));
break bases;
}
}
}
Collections.sort(entries, new FieldComparator("year"));
StringBuilder sb = new StringBuilder();
int i=0;
for (BibtexEntry entry : entries) {
if (i > 0)
sb.append(",");
sb.append(entry.getCiteKey());
i++;
}
String keyString = sb.toString();
boolean inParenthesis = true;
// Insert bookmark:
String bName = getUniqueReferenceMarkName(keyString,
inParenthesis ? AUTHORYEAR_PAR : AUTHORYEAR_INTEXT);
insertReferenceMark(bName, "tmp", mxDocCursor, true, style);
names[piv+1] = bName;
madeModifications = true;
}
piv++;
}
if (madeModifications) {
updateSortedReferenceMarks();
refreshCiteMarkers(databases, style);
}
}
public void testFrameHandling() throws Exception {
XController oldController = mxDoc.getCurrentController();
PropertyValue[] props = new PropertyValue[2];
props[0] = new PropertyValue();
props[0].Name = "Model";
props[0].Value = mxDoc.getCurrentController().getModel();
props[1] = new PropertyValue();
props[1].Name = "Hidden";
props[1].Value = true;
// argument xModel wins over URL.
System.out.println("her");
XComponent comp = xComponentLoader.loadComponentFromURL("private:factory/swriter",
"_blank", 0, props);
System.out.println("her2");
XTextDocument newDoc = (XTextDocument)UnoRuntime.queryInterface(
XTextDocument.class, comp);
System.out.println("newDoc = "+newDoc);
// Controller of the hidden frame
XController xController = newDoc.getCurrentController();
XFrame xFrame = xController.getFrame();
XWindow xContainerWindow = xFrame.getContainerWindow();
XWindow xComponentWindow = xFrame.getComponentWindow();
//xContainerWindow.setVisible(true);
//xComponentWindow.setFocus();
//xContainerWindow.setVisible(false);
xFrame.dispose();
}
}