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

org.odftoolkit.odfdom.changes.TextContainingElement 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
/*
 * Copyright 2012 The Apache Software Foundation.
 *
 * Licensed 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.changes;

import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.logging.Logger;
import org.odftoolkit.odfdom.dom.element.OdfStylableElement;
import org.odftoolkit.odfdom.dom.element.text.TextAElement;
import org.odftoolkit.odfdom.dom.element.text.TextSpanElement;
import org.odftoolkit.odfdom.dom.style.OdfStyleFamily;
import org.odftoolkit.odfdom.incubator.doc.style.OdfStyle;
import org.odftoolkit.odfdom.pkg.OdfElement;
import org.odftoolkit.odfdom.pkg.OdfFileDom;
import org.odftoolkit.odfdom.pkg.OdfName;

/**
 * DOM container to be used for all ODF elements containing "stylable text"
 *
 * 

All text handling is capsulated into this class. * * @author svante.schubertATgmail.com */ public abstract class TextContainingElement extends OdfStylableElement { private static final Logger LOG = Logger.getLogger(TextContainingElement.class.getName()); private TreeSet mSelections = null; /** * Create the instance of TextParagraphElementBase * * @param ownerDoc The type is OdfFileDom * @param elementName name of the stylable element containing text * @param styleFamily the style family of the element * @param styleAttrName e.g. depends on the related @style:family for it * is @text:style-name */ public TextContainingElement( OdfFileDom ownerDoc, OdfName elementName, OdfStyleFamily styleFamily, OdfName styleAttrName) { super(ownerDoc, elementName, styleFamily, styleAttrName); } @Override public OdfName getOdfName() { throw new UnsupportedOperationException("Not supported yet."); } /** * only being used to create the root of all components, representing the document without a * parent element */ private class SelectionComparator implements Comparator { @Override public int compare(TextSelection o1, TextSelection o2) { int firstGreater = o1.compareTo(o2); return firstGreater; } } /** * @param outerSelection as the end position was prior just given for a merge the an outer * selection will be added. Earlier added selection as similar positions are therefore called * "inner" selections and do have a higher priority (as inner overwrites outer) * @return the element that is being kept (sometimes the element of the given selection had to be * dismissed, sometimes even the parent, when an empty element was deleted). */ public OdfElement appendTextSelection(TextSelection outerSelection) { if (this.mSelections == null) { Comparator c = new SelectionComparator(); mSelections = new TreeSet(c); } OdfElement parentElement = (OdfElement) outerSelection.mSelectionElement.getParentNode(); // empty anchor does not make any sense.. if ((outerSelection.mSelectionElement instanceof TextSpanElement || outerSelection.mSelectionElement instanceof TextAElement) && outerSelection.mSelectionElement.getChildNodes().getLength() != 0) { /* Working NOTE: * We need to keep the Anchors, what about the element with URL null, can I remove the anchor right away, or shall I do it here? * Adjust upper SAX parsing part */ // there can always be only one element in a range // Anchor will be triggering an operation after the text content is parsed if (outerSelection.mSelectionElement instanceof TextAElement) { TextAElement outerAnchor = (TextAElement) outerSelection.mSelectionElement; String url = ((TextAElement) outerAnchor).getXlinkHrefAttribute(); TextHyperlinkSelection overlappingInnerSelection = ((TextHyperlinkSelection) outerSelection).getOverLappingHyperlinkSelection(mSelections); if (overlappingInnerSelection != null) { // we need to split the old anchor // split the outer element at the end of the inner anchor element (end first, to avoid // counting invalidity) outerAnchor.split( overlappingInnerSelection.mEndPosition.get( overlappingInnerSelection.mEndPosition.size() - 1)); // split the outer element at the beginning of the inner anchor element OdfElement newMiddlePart = outerAnchor.split( overlappingInnerSelection.mStartPosition.get( overlappingInnerSelection.mStartPosition.size() - 1)); // remove the outer anchor element of the middle part (now top element) OdfElement.removeSingleElement(newMiddlePart); } else if (url == null || url.isEmpty() || url.equals("null")) { parentElement = (OdfElement) OdfElement.removeSingleElement(outerAnchor); } else if (mSelections.contains(outerSelection)) { // if there are is another span/anchor // we need to remove the new outerAnchor from the DOM keeping its children/ancestors SortedSet equalSet = mSelections.subSet(outerSelection, true, outerSelection, true); if (equalSet.size() < 2) { TextSelection innerSelection; Iterator it = equalSet.iterator(); while (it.hasNext()) { innerSelection = it.next(); if (innerSelection.mSelectionElement instanceof TextSpanElement) { if (innerSelection.getURL() == null) { innerSelection.setURL(url); parentElement = (OdfElement) outerAnchor.getParentNode(); break; // as there can only be one anchor } else { // if there is only a span selection, but the URL was already set, remove the new // anchor! parentElement = (OdfElement) OdfElement.removeSingleElement(outerAnchor); break; } } else if (innerSelection.mSelectionElement instanceof TextAElement) { parentElement = (OdfElement) OdfElement.removeSingleElement(outerAnchor); } else { // field mSelections.add(outerSelection); parentElement = (OdfElement) outerSelection.mSelectionElement.getParentNode(); } } } else { // if there are more than two selections (span & anchor) remove the new anchor!) parentElement = (OdfElement) OdfElement.removeSingleElement(outerAnchor); } } else { mSelections.add(outerSelection); // parentElement = (OdfElement) outerSelection.mSelectionElement.getParentNode(); } // if there is already a at the same position, merge the styles } else if (mSelections.contains(outerSelection)) { // receives all spans and anchors that already exist for this position SortedSet equalSet = mSelections.subSet(outerSelection, true, outerSelection, true); TextSelection innerSelection = null; Iterator it = equalSet.iterator(); parentElement = (OdfElement) outerSelection.mSelectionElement.getParentNode(); while (it.hasNext()) { innerSelection = it.next(); if (innerSelection.mSelectionElement instanceof TextSpanElement) { OdfStylableElement innerElement = (OdfStylableElement) innerSelection.getSelectionElement(); OdfStylableElement outerElement = (OdfStylableElement) outerSelection.getSelectionElement(); OdfStyle.mergeSelectionWithSameRange(innerElement, outerElement); } else { String url = innerSelection.getURL(); mSelections.remove(innerSelection); outerSelection.setURL(url); mSelections.add(outerSelection); } } } else { mSelections.add(outerSelection); } } else { // EMPTY ELEMENT // Remove empty elements, unless it is the last and only text span // if (outerSelection.mSelectionElement instanceof TextSpanElement && // parentElement.getChildNodes().getLength() != 1) { parentElement.removeChild(outerSelection.mSelectionElement); // } } return parentElement; } public Collection getTextSelections() { return mSelections; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy