package nota.oxygen.common; import javax.swing.text.BadLocationException; import ro.sync.ecss.extensions.api.ArgumentsMap; import ro.sync.ecss.extensions.api.AuthorAccess; import ro.sync.ecss.extensions.api.AuthorDocumentController; import ro.sync.ecss.extensions.api.AuthorOperation; import ro.sync.ecss.extensions.api.AuthorOperationException; import ro.sync.ecss.extensions.api.access.AuthorEditorAccess; import ro.sync.ecss.extensions.api.node.AuthorElement; import ro.sync.ecss.extensions.api.node.AuthorNode; /** * Abstract base class for {@link AuthorOperation} providing convenience methods * @author Ole Holst Andersen (oha@nota.nu) */ public abstract class BaseAuthorOperation implements AuthorOperation { private AuthorAccess authorAccess; protected abstract void doOperation() throws AuthorOperationException; protected abstract void parseArguments(ArgumentsMap args) throws IllegalArgumentException; /** * Finds a AuthorElement by XPath - the search is context based using a given context * @param xpath The XPath statement * @param context The AuthorNode used as context * @return The matching AuthorElement or null if no match is found * @throws AuthorOperationException */ public AuthorElement findElementByXPath(String xpath, AuthorNode context) throws AuthorOperationException { return getFirstElement(getAuthorAccess().getDocumentController().findNodesByXPath(xpath, context, true, true, true, true)); } /** * Finds a AuthorElement by XPath - the search is global and finds the first matching element in the document * @param xpath * @return The matching AuthorElement or null if no match is found * @throws AuthorOperationException */ public AuthorElement findElementByXPath(String xpath) throws AuthorOperationException { return getFirstElement(getAuthorAccess().getDocumentController().findNodesByXPath(xpath, true, true, true)); } public AuthorElement getFirstElement(AuthorNode[] nodes) { for (int i=0; i<nodes.length; i++) { if (nodes[i] instanceof AuthorElement) return (AuthorElement)nodes[i]; } return null; } /** * Gets the start of the current selection * @return The start of the selection */ public int getSelectionStart() { int selStart = getAuthorAccess().getEditorAccess().getSelectionStart(); int selEnd = getAuthorAccess().getEditorAccess().getSelectionEnd(); if (selStart<selEnd) return selStart; return selEnd; } /** * Gets the end of the current selection * @return The end of the current selection */ public int getSelectionEnd() { int selStart = getAuthorAccess().getEditorAccess().getSelectionStart(); int selEnd = getAuthorAccess().getEditorAccess().getSelectionEnd(); if (selStart<selEnd) return selEnd; return selStart; } @Override public final void doOperation(AuthorAccess aa, ArgumentsMap args) throws IllegalArgumentException, AuthorOperationException { authorAccess = aa; parseArguments(args); AuthorDocumentController docCtrl = getAuthorAccess().getDocumentController(); docCtrl.beginCompoundEdit(); try { doOperation(); } catch (AuthorOperationException e) { docCtrl.cancelCompoundEdit(); throw e; } docCtrl.endCompoundEdit(); } protected boolean showOkCancelMessage(String title, String message) { int answer = getAuthorAccess().getWorkspaceAccess().showConfirmDialog( title, message, new String[] {"OK", "Cancel"}, new int[] {0, 1}); return answer==0; } protected boolean showOkCancelMessage(String message) { return showOkCancelMessage(getDescription(), message); } protected int showYesNoCancelMessage(String title, String message, int defaultButton) { int index = 0; if (defaultButton==0) index = 1; if (defaultButton==-1) index = 2; return getAuthorAccess().getWorkspaceAccess().showConfirmDialog( title, message, new String[] {"Yes", "No", "Cancel"}, new int[] {1, 0, -1}, index); } protected int showYesNoCancelMessage(String message, int defaultButton) { return showYesNoCancelMessage(getDescription(), message, defaultButton); } protected void showMessage(String title, String message){ getAuthorAccess().getWorkspaceAccess().showConfirmDialog( title, message, new String[] {"OK"}, new int[] {0}); } protected void showMessage(String message) { showMessage(getDescription(), message); } /** * Gets the common parent {@link AuthorNode} of the current selection * @return The common parent {@link AuthorNode} * @throws AuthorOperationException * When the current does not have a common parent {@link AuthorNode} */ public AuthorNode getCommonParentNodeOfSelection() throws AuthorOperationException { AuthorDocumentController docCtrl = getAuthorAccess().getDocumentController(); AuthorEditorAccess edtAccess = getAuthorAccess().getEditorAccess(); try { AuthorNode parent = docCtrl.getCommonParentNode( docCtrl.getAuthorDocumentNode(), edtAccess.getSelectionStart(), edtAccess.getSelectionEnd()); if (parent.getType()==AuthorNode.NODE_TYPE_ELEMENT) { AuthorElement elem = (AuthorElement)parent; for (AuthorNode c : elem.getContentNodes()) { if (c.getStartOffset()==edtAccess.getSelectionStart() && c.getEndOffset()==edtAccess.getSelectionEnd()-1) { return c; } } } return parent; } catch (BadLocationException e) { throw new AuthorOperationException("Current selection does not have a common parent node", e); } } /** * Get the common parent {@link AuthorElement} of the current selection * @return The common parent {@link AuthorElement} * @throws AuthorOperationException * When the current selection does not have a common parent {@link AuthorElement} */ public AuthorElement getCommonParentElementOfSelection() throws AuthorOperationException { return Utils.getAncestorOrSelfElement(getCommonParentNodeOfSelection()); } /** * Gets the common parent {@link AuthorElement} with the given QName of the current selection * @param ln The local-name part of the QName * @param ns The name-space part of the QName * - if {@code null} the common parent {@link AuthorElement} with the given local-name is returned * @return The common parent {@link AuthorElement} with the given QName * or {@code null} if no such common parent {@link AuthorElement} exists * @throws AuthorOperationException * When the current selection has no common parent {@link AuthorElement} (with any QName) */ public AuthorElement getNamedCommonParentElementOfSelection(String ln, String ns) throws AuthorOperationException { AuthorElement curElem = getCommonParentElementOfSelection(); while (true) { if (ns==null) { if (curElem.getLocalName().equals(ln)) return curElem; } else { if (curElem.getLocalName().equals(ln) && curElem.getNamespace().equals(ns)) return curElem; } if (!(curElem.getParent() instanceof AuthorElement)) return null; curElem = (AuthorElement)curElem.getParent(); } } /** * Gets the element at a given offset * @param offset - the offset * @return The AuthorElement at the given offset - or null if non-existant * @throws BadLocationException */ public AuthorElement getElementAtOffset(int offset) throws BadLocationException { AuthorNode aNode = getAuthorAccess().getDocumentController().getNodeAtOffset(offset); while (aNode != null) { if (aNode instanceof AuthorElement) { return (AuthorElement)aNode; } aNode = aNode.getParent(); } return null; } /** * Gets the element at the caret position * @return The AuthorElement at the caret position or null if no such AuthorElement exists * @throws BadLocationException */ public AuthorElement getCurrentElement() throws BadLocationException { return getElementAtOffset(getAuthorAccess().getEditorAccess().getBalancedSelectionStart()); } protected AuthorAccess getAuthorAccess() { return authorAccess; } /** * Serializes a {@link AuthorNode} to it's xml representation, including all content nodes * @param input The {@link AuthorNode} to serialize * @return The serialized xml representation * @throws AuthorOperationException * When the given {@link AuthorNode} unexpectedly could not be serialized */ public String serialize(AuthorNode input) throws AuthorOperationException { return Utils.serialize(getAuthorAccess(), input); } /** * Serialized a {@link AuthorNode}, optionally including all content nodes * @param input The {@link AuthorNode} to serialize * @param copyContent A {@link Boolean} indicating if content nodes should also be serailized * @return The serialized xml representation * @throws AuthorOperationException * When the given {@link AuthorNode} unexpectedly could not be serialized */ public String serialize(AuthorNode input, boolean copyContent) throws AuthorOperationException { return Utils.serialize(getAuthorAccess(), input, copyContent); } /** * Serializes the children of an AuthorElement to xml * @param elem The parent AuthorElement * @return The xml representing the children * @throws AuthorOperationException */ public String serializeChildren(AuthorElement elem) throws AuthorOperationException { return Utils.serializeChildren(getAuthorAccess(), elem); } /** * Serializes all children of a AuthorElement, including text nodes * @param aElem The parent AuthorElement * @return the serialized child nodes, an empty string of the AuthorElement is empty * @throws AuthorOperationException */ public String serializeContent(AuthorElement aElem) throws AuthorOperationException { return Utils.serializeContent(getAuthorAccess(), aElem); } }