/* * $Id$ * * Copyright (c) 2004-2005 by the TeXlapse Team. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package net.sourceforge.texlipse.bibeditor; import java.io.IOException; import java.io.StringReader; import java.util.Arrays; import java.util.Iterator; import java.util.List; import net.sourceforge.texlipse.TexlipsePlugin; import net.sourceforge.texlipse.bibparser.BibOutlineContainer; import net.sourceforge.texlipse.bibparser.BibParser; import net.sourceforge.texlipse.editor.TexDocumentParseException; import net.sourceforge.texlipse.model.MarkerHandler; import net.sourceforge.texlipse.model.ParseErrorMessage; import net.sourceforge.texlipse.model.ReferenceContainer; import net.sourceforge.texlipse.model.ReferenceEntry; import net.sourceforge.texlipse.properties.TexlipseProperties; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.BadPositionCategoryException; import org.eclipse.jface.text.IDocument; import org.eclipse.ui.part.FileEditorInput; /** * Document model for the BibTeX -editor. * * @author Oskar Ojala */ public class BibDocumentModel { private BibEditor editor; private List entryList; private List abbrevs; private AbbrevManager abbrManager; private ReferenceContainer bibContainer; /** * Constructs a new document model. * * @param editor The editor that this model is associated with. */ public BibDocumentModel(BibEditor editor) { this.editor = editor; abbrManager = new AbbrevManager(); } /** * @return Returns the abbrManager. */ public AbbrevManager getAbbrManager() { return abbrManager; } /** * Parses the BibTeX -document and retrieves parse errors and other useful * data. * * @throws TexDocumentParseException * If there is an error in the document preventing further * parsing */ private void doParse() throws TexDocumentParseException { try { BibParser parser = new BibParser(new StringReader(this.editor.getDocumentProvider().getDocument(this.editor.getEditorInput()).get())); this.entryList = parser.getEntries(); List<ParseErrorMessage> parseErrors = parser.getErrors(); List parseWarnings = parser.getWarnings(); List tasks = parser.getTasks(); MarkerHandler marker = MarkerHandler.getInstance(); marker.clearErrorMarkers(editor); if (parseErrors.size() > 0) { marker.createErrorMarkers(editor, parseErrors); throw new TexDocumentParseException("Fatal errors in file"); } if (parseWarnings.size() > 0) { marker.createErrorMarkers(editor, parseWarnings); } if (tasks.size() > 0) { marker.createTaskMarkers(editor, tasks); } this.abbrevs = parser.getAbbrevs(); } catch (IOException e) { TexlipsePlugin.log("Can't read file.", e); throw new TexDocumentParseException(e); } } /** * Updates the abbreviation data in the abbreviation manager. */ private void updateAbbrManager() { ReferenceEntry[] esar = new ReferenceEntry[abbrevs.size()]; abbrevs.toArray(esar); Arrays.sort(esar); this.abbrManager.setAbbrevs(esar); } /** * Updates the BibTeX -data in the BibTeX-container. */ private void updateBibContainer() { IProject project = editor.getProject(); if (project == null) return; IResource resource = ((FileEditorInput)editor.getEditorInput()).getFile(); if (bibContainer == null) { ReferenceContainer refCon = (ReferenceContainer) TexlipseProperties.getSessionProperty(project, TexlipseProperties.BIBCONTAINER_PROPERTY); if (refCon != null) { bibContainer = refCon; } else { return; } } boolean changed = bibContainer.updateRefSource( resource.getFullPath().removeFirstSegments(1).toString(), entryList); if (changed) { TexlipseProperties.setSessionProperty(project, TexlipseProperties.BIBFILES_CHANGED, new Boolean(true)); } } /** * Updates the outline view when outline.doSave is called. */ private void updateOutline() { BibOutlineContainer boc = new BibOutlineContainer(entryList, true); this.editor.getOutlinePage().update(boc); } /** * Updates the document positions of the outline. These are used both * for outline navigation and code folding. */ private void updateDocumentPositions() { IDocument document = editor.getDocumentProvider().getDocument(editor.getEditorInput()); try { document.removePositionCategory(BibOutlinePage.SEGMENTS); } catch (BadPositionCategoryException bpce) { // do nothing } document.addPositionCategory(BibOutlinePage.SEGMENTS); try { /* int beginOffset = -1, endOffset = -1; ReferenceEntry prev = null, next = null; //Iterator it = currentOutline.iterator(); Iterator it = entryList.iterator(); if (it.hasNext()) { prev = (ReferenceEntry) it.next(); beginOffset = document.getLineOffset(prev.startLine - 1); } while (it.hasNext()) { next = (ReferenceEntry) it.next(); endOffset = document.getLineOffset(next.startLine - 1); int length = endOffset - beginOffset; prev.setPosition(beginOffset, length); document.addPosition(BibOutlinePage.SEGMENTS, prev.position); prev = next; beginOffset = endOffset; } if (beginOffset != -1) { prev.setPosition(beginOffset, document.getLength() - beginOffset); document.addPosition(BibOutlinePage.SEGMENTS, prev.position); } */ // This hack is needed because Eclipse doesn't allow us to get // the offset of the last line in the document if (entryList.isEmpty()) return; int lastLine = document.getNumberOfLines(); ReferenceEntry rel = (ReferenceEntry) entryList.get(entryList.size() - 1); if (rel.endLine == lastLine) { rel.endLine--; } for (Iterator iter = entryList.iterator(); iter.hasNext();) { ReferenceEntry re = (ReferenceEntry) iter.next(); int beginOffset = document.getLineOffset(re.startLine - 1); int length = document.getLineOffset(re.endLine) - beginOffset; re.setPosition(beginOffset, length); document.addPosition(BibOutlinePage.SEGMENTS, re.position); } } catch (BadPositionCategoryException bpce) { TexlipsePlugin.log("BibDocumentModel.updateDocumentPositions: bad position category ", bpce); } catch (BadLocationException ble) { TexlipsePlugin.log("BibDocumentModel.updateDocumentPositions: bad position ", ble); } } /** * Updates the document model. This includes parsing the document * and retrieving updated outline and abbreviation informaiton as * well as updating these into the editor. */ public void update() { try { doParse(); this.updateDocumentPositions(); updateBibContainer(); if (this.editor.getOutlinePage() != null) { this.updateOutline(); } updateAbbrManager(); editor.updateCodeFolder(entryList); } catch (TexDocumentParseException e) { // We do nothing, since the error is already added // TexlipsePlugin.log("There were parse errors in the document", e); } } }