All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.odftoolkit.odfdom.incubator.search.TextSelection Maven / Gradle / Ivy

Go to download

ODFDOM is an OpenDocument Format (ODF) framework. Its purpose is to provide an easy common way to create, access and manipulate ODF files, without requiring detailed knowledge of the ODF specification. It is designed to provide the ODF developer community with an easy lightwork programming API portable to any object-oriented language. The current reference implementation is written in Java.

There is a newer version: 1.0.0-BETA1
Show newest version
/**
 * **********************************************************************
 *
 * 

Licensed to the Apache Software Foundation (ASF) under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional information regarding * copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the License. You may obtain a * copy of the License at * *

http://www.apache.org/licenses/LICENSE-2.0 * *

Unless required by applicable law or agreed to in writing, software distributed under the * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing permissions and * limitations under the License. * *

********************************************************************** */ package org.odftoolkit.odfdom.incubator.search; import java.net.URL; import java.util.Map; import java.util.TreeMap; import org.odftoolkit.odfdom.doc.OdfDocument; import org.odftoolkit.odfdom.dom.OdfDocumentNamespace; import org.odftoolkit.odfdom.dom.element.OdfStylableElement; import org.odftoolkit.odfdom.dom.element.OdfStyleBase; import org.odftoolkit.odfdom.dom.element.text.TextAElement; import org.odftoolkit.odfdom.dom.element.text.TextSElement; import org.odftoolkit.odfdom.dom.style.OdfStyleFamily; import org.odftoolkit.odfdom.dom.style.props.OdfStylePropertiesSet; import org.odftoolkit.odfdom.dom.style.props.OdfStyleProperty; import org.odftoolkit.odfdom.incubator.doc.style.OdfStyle; import org.odftoolkit.odfdom.incubator.doc.text.OdfTextHeading; import org.odftoolkit.odfdom.incubator.doc.text.OdfTextParagraph; import org.odftoolkit.odfdom.incubator.doc.text.OdfTextSpan; import org.odftoolkit.odfdom.incubator.doc.text.OdfWhitespaceProcessor; import org.odftoolkit.odfdom.pkg.OdfElement; import org.odftoolkit.odfdom.pkg.OdfFileDom; import org.w3c.dom.Element; import org.w3c.dom.Node; /** * A TextSelection can describe a sub element in a mParagraph element or a mHeading element. it is * recognized by the container element(which type should be OdfTextParagraph or OdfTextHeadingt), * the start index of the text content of the container element and the text content of this * selection. */ public class TextSelection extends Selection { private String mMatchedText; private OdfTextParagraph mParagraph; private OdfTextHeading mHeading; private int mIndexInContainer; private boolean mIsInserted; /** * Constructor of TextSelection * * @param text the text content of this TextSelection * @param containerElement the mParagraph element or mHeading element that contain this * TextSelection * @param index the start index of the text content of the container element */ TextSelection(String text, OdfElement containerElement, int index) { mMatchedText = text; if (containerElement instanceof OdfTextParagraph) { mParagraph = (OdfTextParagraph) containerElement; } else if (containerElement instanceof OdfTextHeading) { mHeading = (OdfTextHeading) containerElement; } mIndexInContainer = index; } /** * Get the mParagraph element or mHeading element that contain this TextSelection * * @return OdfElement the container element */ @Override public OdfElement getElement() { return getContainerElement(); } /** * Get the mParagraph element or mHeading element that contain this text * * @return OdfElement */ public OdfElement getContainerElement() { if (mParagraph != null) { return mParagraph; } else { return mHeading; } } /** * Get the start index of the text content of its container element * * @return index the start index of the text content of its container element */ @Override public int getIndex() { return mIndexInContainer; } /** * Get the text content of this TextSelection * * @return text the text content */ public String getText() { return mMatchedText; } /* * Validate if the selection is still available. * @return true if the selection is available; false if the selection is not available. */ private boolean validate() { if (getContainerElement() == null) { return false; } OdfElement container = getContainerElement(); if (container == null) { return false; } OdfWhitespaceProcessor textProcessor = new OdfWhitespaceProcessor(); String content = textProcessor.getText(container); if (content.indexOf(mMatchedText, mIndexInContainer) == mIndexInContainer) { return true; } else { return false; } } /** * Delete the selection from the document the other matched selection in the same container * element will be updated automatically because the start index of the following selections will * be changed when the previous selection has been deleted * * @throws InvalidNavigationException if the selection is unavailable. */ @Override public void cut() throws InvalidNavigationException { if (validate() == false) { throw new InvalidNavigationException("No matched string at this position"); } OdfElement container = getContainerElement(); delete(mIndexInContainer, mMatchedText.length(), container); SelectionManager.refreshAfterCut(this); mMatchedText = ""; } /** * Apply a style to the selection so that the text style of this selection will append the * specified style * * @param style the style can be from the current document or user defined * @throws InvalidNavigationException if the selection is unavailable. */ public void applyStyle(OdfStyleBase style) throws InvalidNavigationException { // append the specified style to the selection if (validate() == false) { throw new InvalidNavigationException("No matched string at this position"); } OdfElement parentElement = getContainerElement(); int leftLength = getText().length(); int index = mIndexInContainer; appendStyle(index, leftLength, parentElement, style); } /* * append specified style for a range text of pNode * from 'fromindex' and cover 'leftLength' */ private void appendStyle(int fromindex, int leftLength, Node pNode, OdfStyleBase style) { if ((fromindex == 0) && (leftLength == 0)) { return; } int nodeLength = 0; Node node = pNode.getFirstChild(); OdfWhitespaceProcessor textProcessor = new OdfWhitespaceProcessor(); while (node != null) { if ((fromindex == 0) && (leftLength == 0)) { return; } if (node.getNodeType() == Node.TEXT_NODE) { nodeLength = node.getNodeValue().length(); } else if (node.getNodeType() == Node.ELEMENT_NODE) { if (node.getLocalName().equals("s")) // text:s { try { nodeLength = Integer.parseInt( ((Element) node).getAttributeNS(OdfDocumentNamespace.TEXT.getUri(), "c")); } catch (Exception e) { nodeLength = 1; } } else if (node.getLocalName().equals("line-break")) { nodeLength = 1; } else if (node.getLocalName().equals("tab")) { nodeLength = 1; } else { nodeLength = textProcessor.getText((OdfElement) node).length(); } } if (nodeLength <= fromindex) { fromindex -= nodeLength; } else { // the start index is in this node if (node.getNodeType() == Node.TEXT_NODE || (node.getNodeType() == Node.ELEMENT_NODE && node.getLocalName().equals("s"))) { int endLength = fromindex + leftLength; int nextLength = nodeLength - endLength; String value = null; if (node.getNodeType() == Node.TEXT_NODE) { value = node.getNodeValue(); node.setNodeValue(value.substring(0, fromindex)); } else { ((TextSElement) node).setTextCAttribute(fromindex); } Node nextNode = node.getNextSibling(); Node parNode = node.getParentNode(); // init text:span OdfTextSpan textSpan = new OdfTextSpan((OdfFileDom) node.getOwnerDocument()); Node newNode = null; if (nextLength >= 0) { newNode = node.cloneNode(true); if (node.getNodeType() == Node.TEXT_NODE) { textSpan.setTextContent(value.substring(fromindex, endLength)); newNode.setNodeValue(value.substring(endLength, nodeLength)); } else { Node newS = node.cloneNode(true); ((TextSElement) newS).setTextCAttribute(endLength - fromindex); textSpan.appendChild(newS); ((TextSElement) newNode).setTextCAttribute(nodeLength - endLength); } leftLength = 0; } else { if (node.getNodeType() == Node.TEXT_NODE) { textSpan.setTextContent(value.substring(fromindex, nodeLength)); } else { Node newS = node.cloneNode(true); ((TextSElement) newS).setTextCAttribute(nodeLength - fromindex); textSpan.appendChild(newS); } leftLength = endLength - nodeLength; } textSpan.setProperties(style.getStyleProperties()); if (nextNode != null) { parNode.insertBefore(textSpan, nextNode); if (newNode != null) { parNode.insertBefore(newNode, nextNode); } } else { parNode.appendChild(textSpan); if (newNode != null) { parNode.appendChild(newNode); } } if (fromindex == 0) // node only contains the prefix, is it empty? { parNode.removeChild(node); } fromindex = 0; if (nextNode != null) { node = nextNode; } else { node = textSpan; } } else if (node.getNodeType() == Node.ELEMENT_NODE) { assert (!node.getLocalName().equals("s")); // was handled above if (node.getLocalName().equals("line-break") || node.getLocalName().equals("tab")) { fromindex = 0; leftLength--; } else { appendStyle(fromindex, leftLength, node, style); int length = (fromindex + leftLength) - nodeLength; leftLength = length > 0 ? length : 0; fromindex = 0; } } } node = node.getNextSibling(); } } /** * Replace the text content of selection with a new string * * @param newText the replace text String * @throws InvalidNavigationException if the selection is unavailable. */ public void replaceWith(String newText) throws InvalidNavigationException { if (validate() == false) { throw new InvalidNavigationException("No matched string at this position"); } OdfElement parentElement = getContainerElement(); int leftLength = getText().length(); int index = mIndexInContainer; delete(index, leftLength, parentElement); OdfTextSpan textSpan = new OdfTextSpan((OdfFileDom) parentElement.getOwnerDocument()); textSpan.addContentWhitespace(newText); /*if (startElement instanceof OdfStyleBase) textSpan.setProperties(((OdfStyleBase) startElement) .getStyleProperties());*/ mIsInserted = false; insertSpan(textSpan, index, parentElement); // optimize the parent element optimize(parentElement); int offset = newText.length() - leftLength; SelectionManager.refresh(this.getContainerElement(), offset, index + getText().length()); mMatchedText = newText; } /** * Paste this selection just before a specific selection. * * @param positionItem a selection that is used to point out the position * @throws InvalidNavigationException if the selection is unavailable. */ @Override public void pasteAtFrontOf(Selection positionItem) throws InvalidNavigationException { if (validate() == false) { throw new InvalidNavigationException("No matched string at this position"); } int indexOfNew = 0; OdfElement newElement = positionItem.getElement(); if (positionItem instanceof TextSelection) { indexOfNew = ((TextSelection) positionItem).getIndex(); newElement = ((TextSelection) positionItem).getContainerElement(); } OdfTextSpan textSpan = getSpan((OdfFileDom) positionItem.getElement().getOwnerDocument()); mIsInserted = false; insertSpan(textSpan, indexOfNew, newElement); adjustStyle(newElement, textSpan, null); SelectionManager.refreshAfterPasteAtFrontOf(this, positionItem); } /** * Paste this selection just after a specific selection. * * @param positionItem a selection that is used to point out the position * @throws InvalidNavigationException if the selection is unavailable. */ @Override public void pasteAtEndOf(Selection positionItem) throws InvalidNavigationException { if (validate() == false) { throw new InvalidNavigationException("No matched string at this position"); } int indexOfNew = 0; // TODO: think about and test if searchitem is a element selection OdfElement newElement = positionItem.getElement(); if (positionItem instanceof TextSelection) { indexOfNew = ((TextSelection) positionItem).getIndex() + ((TextSelection) positionItem).getText().length(); newElement = ((TextSelection) positionItem).getContainerElement(); } OdfTextSpan textSpan = getSpan((OdfFileDom) positionItem.getElement().getOwnerDocument()); mIsInserted = false; insertSpan(textSpan, indexOfNew, newElement); adjustStyle(newElement, textSpan, null); SelectionManager.refreshAfterPasteAtEndOf(this, positionItem); } /** * Add a hypertext reference to the selection * * @param url the url of the hypertext reference * @throws InvalidNavigationException if the selection is unavailable. */ public void addHref(URL url) throws InvalidNavigationException { if (validate() == false) { throw new InvalidNavigationException("No matched string at this position"); } OdfElement parentElement = getContainerElement(); int leftLength = getText().length(); int index = mIndexInContainer; addHref(index, leftLength, parentElement, url.toString()); } /* * add href for a range text of pNode from the 'fromindex' text, and the href will cover * 'leftLength' text * */ private void addHref(int fromindex, int leftLength, Node pNode, String href) { if ((fromindex == 0) && (leftLength == 0)) { return; } int nodeLength = 0; Node node = pNode.getFirstChild(); OdfWhitespaceProcessor textProcessor = new OdfWhitespaceProcessor(); while (node != null) { if ((fromindex == 0) && (leftLength == 0)) { return; } if (node.getNodeType() == Node.TEXT_NODE) { nodeLength = node.getNodeValue().length(); } else if (node.getNodeType() == Node.ELEMENT_NODE) { if (node.getLocalName().equals("s")) // text:s { try { nodeLength = Integer.parseInt( ((Element) node).getAttributeNS(OdfDocumentNamespace.TEXT.getUri(), "c")); } catch (Exception e) { nodeLength = 1; } } else if (node.getLocalName().equals("line-break")) { nodeLength = 1; } else if (node.getLocalName().equals("tab")) { nodeLength = 1; } else { nodeLength = textProcessor.getText((OdfElement) node).length(); } } if (nodeLength <= fromindex) { fromindex -= nodeLength; } else { // the start index is in this node if (node.getNodeType() == Node.TEXT_NODE || (node.getNodeType() == Node.ELEMENT_NODE && node.getLocalName().equals("s"))) { int endLength = fromindex + leftLength; int nextLength = nodeLength - endLength; String value = null; if (node.getNodeType() == Node.TEXT_NODE) { value = node.getNodeValue(); node.setNodeValue(value.substring(0, fromindex)); } else { ((TextSElement) node).setTextCAttribute(fromindex); } Node nextNode = node.getNextSibling(); Node parNode = node.getParentNode(); // init text:a TextAElement textLink = new TextAElement((OdfFileDom) node.getOwnerDocument()); Node newNode = null; if (nextLength >= 0) { newNode = node.cloneNode(true); if (node.getNodeType() == Node.TEXT_NODE) { textLink.setTextContent(value.substring(fromindex, endLength)); newNode.setNodeValue(value.substring(endLength, nodeLength)); } else { Node newS = node.cloneNode(true); ((TextSElement) newS).setTextCAttribute(endLength - fromindex); textLink.appendChild(newS); ((TextSElement) newNode).setTextCAttribute(nodeLength - endLength); } leftLength = 0; } else { if (node.getNodeType() == Node.TEXT_NODE) { textLink.setTextContent(value.substring(fromindex, value.length())); } else { Node newS = node.cloneNode(true); ((TextSElement) newS).setTextCAttribute(nodeLength - fromindex); textLink.appendChild(newS); } leftLength = endLength - nodeLength; } textLink.setXlinkTypeAttribute("simple"); textLink.setXlinkHrefAttribute(href); if (nextNode != null) { parNode.insertBefore(textLink, nextNode); if (newNode != null) { parNode.insertBefore(newNode, nextNode); } } else { parNode.appendChild(textLink); if (newNode != null) { parNode.appendChild(newNode); } } if (fromindex == 0) // node only contains the prefix, is it empty? { parNode.removeChild(node); } fromindex = 0; if (nextNode != null) { node = nextNode; } else { node = textLink; } } else if (node.getNodeType() == Node.ELEMENT_NODE) { assert (!node.getLocalName().equals("s")); // was handled above if (node.getLocalName().equals("line-break") || node.getLocalName().equals("tab")) { fromindex = 0; leftLength--; } else { addHref(fromindex, leftLength, node, href); int length = (fromindex + leftLength) - nodeLength; leftLength = length > 0 ? length : 0; fromindex = 0; } } } node = node.getNextSibling(); } } /* * delete the pNode from the fromindex text, and delete leftLength text */ private void delete(int fromindex, int leftLength, Node pNode) { if ((fromindex == 0) && (leftLength == 0)) { return; } int nodeLength = 0; Node node = pNode.getFirstChild(); OdfWhitespaceProcessor textProcessor = new OdfWhitespaceProcessor(); while (node != null) { if ((fromindex == 0) && (leftLength == 0)) { return; } if (node.getNodeType() == Node.TEXT_NODE) { nodeLength = node.getNodeValue().length(); } else if (node.getNodeType() == Node.ELEMENT_NODE) { if (node.getLocalName().equals("s")) // text:s { try { nodeLength = Integer.parseInt( ((Element) node).getAttributeNS(OdfDocumentNamespace.TEXT.getUri(), "c")); } catch (Exception e) { nodeLength = 1; } } else if (node.getLocalName().equals("line-break")) { nodeLength = 1; } else if (node.getLocalName().equals("tab")) { nodeLength = 1; } else { nodeLength = textProcessor.getText((OdfElement) node).length(); } } if (nodeLength <= fromindex) { fromindex -= nodeLength; } else { // the start index is in this node if (node.getNodeType() == Node.TEXT_NODE) { String value = node.getNodeValue(); StringBuffer buffer = new StringBuffer(); buffer.append(value.substring(0, fromindex)); int endLength = fromindex + leftLength; int nextLength = value.length() - endLength; fromindex = 0; if (nextLength >= 0) { // delete the result buffer.append(value.substring(endLength, value.length())); leftLength = 0; } else { leftLength = endLength - value.length(); } node.setNodeValue(buffer.toString()); } else if (node.getNodeType() == Node.ELEMENT_NODE) { // if text:s????????? if (node.getLocalName().equals("s")) // text:s { // delete space if (0 < fromindex || leftLength < nodeLength) { final int deleted = Math.min(leftLength, nodeLength - fromindex); ((TextSElement) node).setTextCAttribute(new Integer(nodeLength - deleted)); leftLength = leftLength - deleted; } else { Node nodeMerker = node.getNextSibling(); pNode.removeChild(node); node = nodeMerker; leftLength = leftLength - nodeLength; } fromindex = 0; continue; } else if (node.getLocalName().equals("line-break") || node.getLocalName().equals("tab")) { fromindex = 0; leftLength--; } else { delete(fromindex, leftLength, node); int length = (fromindex + leftLength) - nodeLength; leftLength = length > 0 ? length : 0; fromindex = 0; } } } node = node.getNextSibling(); } } @Override protected void refreshAfterFrontalDelete(Selection deleteItem) { if (deleteItem instanceof TextSelection) { mIndexInContainer -= ((TextSelection) deleteItem).getText().length(); } } @Override protected void refreshAfterFrontalInsert(Selection pasteItem) { if (pasteItem instanceof TextSelection) { mIndexInContainer += ((TextSelection) pasteItem).getText().length(); } } @Override protected void refresh(int offset) { mIndexInContainer += offset; } /** * return a String Object representing this selection value the text content of the selection, * start index in the container element and the text content of the container element will be * provided * * @return a String representation of the value of this TextSelection */ @Override public String toString() { OdfWhitespaceProcessor textProcessor = new OdfWhitespaceProcessor(); return "[" + mMatchedText + "] started from " + mIndexInContainer + " in paragraph:" + textProcessor.getText(getContainerElement()); } // return a new span that cover this selection // and keep the original style of this selection private OdfTextSpan getSpan(OdfFileDom ownerDoc) { OdfElement parentElement = getContainerElement(); if (parentElement != null) { Node copyParentNode = parentElement.cloneNode(true); if (ownerDoc != parentElement.getOwnerDocument()) { copyParentNode = ownerDoc.adoptNode(copyParentNode); } OdfTextSpan textSpan = new OdfTextSpan(ownerDoc); int sIndex = mIndexInContainer; int eIndex = sIndex + mMatchedText.length(); // delete the content except the selection string // delete from the end to start, so that the postion will not be // impact by delete action OdfWhitespaceProcessor textProcessor = new OdfWhitespaceProcessor(); delete(eIndex, textProcessor.getText(copyParentNode).length() - eIndex, copyParentNode); delete(0, sIndex, copyParentNode); optimize(copyParentNode); Node childNode = copyParentNode.getFirstChild(); while (childNode != null) { textSpan.appendChild(childNode.cloneNode(true)); childNode = childNode.getNextSibling(); } // apply text style for the textSpan if (copyParentNode instanceof OdfStylableElement) { applyTextStyleProperties( getTextStylePropertiesDeep((OdfStylableElement) copyParentNode), textSpan); } return textSpan; } return null; } /* * optimize the text element by deleting the empty text node * * @param element */ private void optimize(Node pNode) { // check if the text:a can be optimized OdfWhitespaceProcessor textProcess = new OdfWhitespaceProcessor(); Node node = pNode.getFirstChild(); while (node != null) { Node nextNode = node.getNextSibling(); // if ((node.getNodeType() == Node.ELEMENT_NODE) && (node.getPrefix().equals("text"))) { if (node instanceof OdfTextSpan) { if (textProcess.getText(node).length() == 0) { node.getParentNode().removeChild(node); } else { optimize(node); } } node = nextNode; } } /* * apply the styleMap to the toElement * reserve the style property of toElement if it is also exist in styleMap */ private void applyTextStyleProperties( Map styleMap, OdfStylableElement toElement) { if (styleMap != null) { // preserve the style property of toElement if it is also exist in styleMap OdfStyle resultStyleElement = toElement.getOrCreateAutomaticStyles().newStyle(OdfStyleFamily.Text); for (Map.Entry entry : styleMap.entrySet()) { if (toElement.hasProperty(entry.getKey())) { resultStyleElement.setProperty(entry.getKey(), toElement.getProperty(entry.getKey())); } else { resultStyleElement.setProperty(entry.getKey(), entry.getValue()); } } toElement.setStyleName(resultStyleElement.getStyleNameAttribute()); } } /* * insert textSpan into the from index of pNode */ private void insertSpan(OdfTextSpan textSpan, int fromindex, Node pNode) { if (fromindex < 0) { fromindex = 0; } if (fromindex == 0 && mIsInserted) { return; } OdfWhitespaceProcessor textProcessor = new OdfWhitespaceProcessor(); int nodeLength = 0; Node node = pNode.getFirstChild(); while (node != null) { if (fromindex <= 0 && mIsInserted) { return; } if (node.getNodeType() == Node.TEXT_NODE) { nodeLength = node.getNodeValue().length(); if ((fromindex != 0) && (nodeLength < fromindex)) { fromindex -= nodeLength; } else { // insert result after node, and insert an new text node // after // the result node String value = node.getNodeValue(); StringBuffer buffer = new StringBuffer(); buffer.append(value.substring(0, fromindex)); // insert the text span in appropriate position node.setNodeValue(buffer.toString()); Node nextNode = node.getNextSibling(); Node parNode = node.getParentNode(); Node newNode = node.cloneNode(true); newNode.setNodeValue(value.substring(fromindex, value.length())); if (nextNode != null) { parNode.insertBefore(textSpan, nextNode); parNode.insertBefore(newNode, nextNode); } else { parNode.appendChild(textSpan); parNode.appendChild(newNode); } mIsInserted = true; return; } } else if (node.getNodeType() == Node.ELEMENT_NODE) { if (node.getLocalName().equals("s")) // text:s { try { nodeLength = Integer.parseInt( ((Element) node).getAttributeNS(OdfDocumentNamespace.TEXT.getUri(), "c")); } catch (Exception e) { nodeLength = 1; } fromindex -= nodeLength; } else if (node.getLocalName().equals("line-break")) { nodeLength = 1; fromindex--; } else if (node.getLocalName().equals("tab")) { nodeLength = 1; fromindex--; } else { nodeLength = textProcessor.getText(node).length(); insertSpan(textSpan, fromindex, node); fromindex -= nodeLength; } } node = node.getNextSibling(); } } /* * the textSpan must be the child element of parentNode * this method is used to keep the style of text span when it has been insert into the parentNode * if we don't deal with the style, the inserted span will also have the style of parentNode * */ private void adjustStyle( Node parentNode, OdfTextSpan textSpan, Map styleMap) { if (parentNode instanceof OdfStylableElement) { OdfStylableElement pStyleNode = (OdfStylableElement) parentNode; if (styleMap == null) { styleMap = getTextStylePropertiesDeep(pStyleNode); } Node node = parentNode.getFirstChild(); while (node != null) { if (node.getNodeType() == Node.TEXT_NODE) { if (node.getTextContent().length() > 0) { Node nextNode = node.getNextSibling(); OdfTextSpan span = new OdfTextSpan((OdfFileDom) node.getOwnerDocument()); span.appendChild(node); if (nextNode != null) { parentNode.insertBefore(span, nextNode); } else { parentNode.appendChild(span); } node = span; applyTextStyleProperties(styleMap, (OdfStylableElement) node); } } else if ((node instanceof OdfStylableElement)) { if (!node.equals(textSpan)) { Map styles = getTextStylePropertiesDeep(pStyleNode); Map styles1 = getTextStylePropertiesDeep((OdfStylableElement) node); if (styles == null) { styles = styles1; } else if (styles1 != null) { styles.putAll(styles1); } int comp = node.compareDocumentPosition(textSpan); // if node contains textSpan, then recurse the node if ((comp & Node.DOCUMENT_POSITION_CONTAINED_BY) > 0) { adjustStyle(node, textSpan, styles); } else { applyTextStyleProperties(styles, (OdfStylableElement) node); } } } node = node.getNextSibling(); } // change the parentNode to default style // here we don't know the default style name, so here just // remove the text:style-name attribute pStyleNode.removeAttributeNS(OdfDocumentNamespace.TEXT.getUri(), "style-name"); } } /* * get a map containing text properties of the specified styleable element. * @return a map of text properties. */ private Map getTextStyleProperties(OdfStylableElement element) { String styleName = element.getStyleName(); OdfStyleBase styleElement = element.getOrCreateAutomaticStyles().getStyle(styleName, element.getStyleFamily()); if (styleElement == null) { styleElement = element.getDocumentStyle(); } if (styleElement != null) { // check if it is the style:defaut-style if ((styleElement.getPropertiesElement(OdfStylePropertiesSet.ParagraphProperties) == null) && (styleElement.getPropertiesElement(OdfStylePropertiesSet.TextProperties) == null)) { styleElement = ((OdfDocument) ((OdfFileDom) styleElement.getOwnerDocument()).getDocument()) .getDocumentStyles() .getDefaultStyle(styleElement.getFamily()); } TreeMap result = new TreeMap(); OdfStyleFamily family = OdfStyleFamily.Text; if (family != null) { for (OdfStyleProperty property : family.getProperties()) { if (styleElement.hasProperty(property)) { result.put(property, styleElement.getProperty(property)); } } } return result; } return null; } /* * get a map containing text properties of the specified styleable element. * The map will also include any properties set by parent styles * @return a map of text properties. * */ private Map getTextStylePropertiesDeep(OdfStylableElement element) { String styleName = element.getStyleName(); OdfStyleBase styleElement = element.getOrCreateAutomaticStyles().getStyle(styleName, element.getStyleFamily()); if (styleElement == null) { styleElement = element.getDocumentStyle(); } TreeMap result = new TreeMap(); while (styleElement != null) { // check if it is the style:defaut-style if ((styleElement.getPropertiesElement(OdfStylePropertiesSet.ParagraphProperties) == null) && (styleElement.getPropertiesElement(OdfStylePropertiesSet.TextProperties) == null)) { styleElement = ((OdfDocument) ((OdfFileDom) styleElement.getOwnerDocument()).getDocument()) .getDocumentStyles() .getDefaultStyle(styleElement.getFamily()); } OdfStyleFamily family = OdfStyleFamily.Text; if (family != null) { for (OdfStyleProperty property : family.getProperties()) { if (styleElement.hasProperty(property)) { result.put(property, styleElement.getProperty(property)); } } } styleElement = styleElement.getParentStyle(); } return result; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy