Package org.odftoolkit.simple.common.navigation

Source Code of org.odftoolkit.simple.common.navigation.TextStyleNavigation

/*
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.simple.common.navigation;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.odftoolkit.odfdom.dom.OdfDocumentNamespace;
import org.odftoolkit.odfdom.dom.element.OdfStylableElement;
import org.odftoolkit.odfdom.dom.style.OdfStyleFamily;
import org.odftoolkit.odfdom.dom.style.props.OdfStyleProperty;
import org.odftoolkit.odfdom.incubator.doc.style.OdfDefaultStyle;
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.pkg.OdfElement;
import org.odftoolkit.simple.TextDocument;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
* A derived <code>Navigation</code> class used to navigate the text content,
* which can search the document and find matched style properties and return
* <code>TextSelection</code> instance(s).
*/
public class TextStyleNavigation extends Navigation {

  private TextDocument mTextDocument;
  private TextSelection mNextSelectedItem;
  private TextSelection mTempSelectedItem;
  private int mCurrentIndex;
  private Map<OdfStyleProperty, String> mProps;
  private String mText;
  private Node mPhNode;
  private int mIndex;
  private Node mNode;

  /**
   * Construct <code>TextStyleNavigation</code> with style properties condition and
   * navigation scope.
   *
   * @param props
   *            the matched style properties conditions
   * @param doc
   *            the navigation search scope
   */
  public TextStyleNavigation(Map<OdfStyleProperty, String> props, TextDocument doc) {
    mTextDocument = doc;
    mNextSelectedItem = null;
    mTempSelectedItem = null;
    this.mProps = props;
  }

  /**
   * Check if has next <code>TextSelection</code> with satisfied style.
   *
   * @see org.odftoolkit.simple.common.navigation.Navigation#hasNext()
   */
  @Override
  public boolean hasNext() {
    mTempSelectedItem = findNext(mNextSelectedItem);
    return (mTempSelectedItem != null);
  }
 
  /**
   * Get next <code>TextSelection</code>.
   *
   * @see org.odftoolkit.simple.common.navigation.Navigation#nextSelection()
   */
  @Override
  public Selection nextSelection() {
    if(mTempSelectedItem !=null){
      mNextSelectedItem = mTempSelectedItem;
      mTempSelectedItem = null;
    }else{
      mNextSelectedItem = findNext(mNextSelectedItem);
    }
    if (mNextSelectedItem == null) {
      return null;
    } else {
      Selection.SelectionManager.registerItem(mNextSelectedItem);
      return mNextSelectedItem;
    }
  }

  /**
   * Check if the element has specified style properties, which are stated
   * when the <code>TextStyleNavigation</code> created.
   *
   * @param element
   *            navigate this element
   * @return true if this element has the specified style properties false if
   *         not match
   */
  @Override
  public boolean match(Node element) {
    boolean match = false;
    if (element.getNodeType() == Node.TEXT_NODE && !element.getNodeValue().trim().equals("")) {
      if (element.getParentNode() instanceof OdfStylableElement) {
        OdfStylableElement parStyleElement = (OdfStylableElement) element.getParentNode();
        String parStyleName = getStyleName(parStyleElement);
        if (getMatchStyleNames().contains(parStyleName)) {
          match = true;
          mText = element.getNodeValue();
          NodeList nodes = getPHElement(element.getParentNode()).getChildNodes();
          mIndex = 0;
          getIndex(nodes, element);
        }
      }
    }
    return match;
  }

  /*
   * Find next <code>TextSelection</code> which match specified style.
   */
  private TextSelection findNext(TextSelection selected) {
    OdfElement element = null;
    try {
      Node rootNode = mTextDocument.getContentRoot();
      if (selected == null) {
        mNode = getNextMatchElementInTree(rootNode, rootNode);
      } else {
        mNode = getNextMatchElementInTree(mNode, rootNode);
      }
    } catch (Exception ex) {
      Logger.getLogger(TextStyleNavigation.class.getName()).log(Level.SEVERE, ex.getMessage(), ex);
    }
    if (mNode != null) {
      element = (OdfElement) getPHElement(mNode);
      TextSelection item = new TextSelection(this, mText, element,
          mCurrentIndex);
      return item;
    }
    return null;
  }

  private Node getPHElement(Node node) {
    // get paragraph or heading element
    if (node instanceof OdfTextParagraph) {
      mPhNode = node;
    } else if (node instanceof OdfTextHeading) {
      mPhNode = node;
    } else {
      getPHElement(node.getParentNode());
    }
    return mPhNode;
  }

  private void getIndex(NodeList nodes, Node element) {
    for (int i = 0; i < nodes.getLength(); i++) {
      Node node = nodes.item(i);
      if (node == element) {
        mCurrentIndex = mIndex;
        break;
      } else {
        if (node.getNodeType() == Node.TEXT_NODE) {
          mIndex = mIndex + node.getNodeValue().length();
        } else if (node.getNodeType() == Node.ELEMENT_NODE) {
          // mText:s
          if (node.getLocalName().equals("s")) {
            try {
              mIndex = mIndex
                  + Integer.parseInt(((Element) node).getAttributeNS(OdfDocumentNamespace.TEXT
                      .getUri(), "c"));
            } catch (Exception e) {
              mIndex++;
            }
          } else if (node.getLocalName().equals("line-break")) {
            mIndex++;
          } else if (node.getLocalName().equals("tab")) {
            mIndex++;
          } else {
            getIndex(node.getChildNodes(), element);
          }
        }
      }
    }
  }

  private String getStyleName(OdfStylableElement element) {
    String stylename = element.getStyleName();
    if (stylename == null) {
      if (element.getParentNode() instanceof OdfStylableElement) {
        getStyleName((OdfStylableElement) element.getParentNode());
      } else {
        stylename = "defaultstyle";
      }
    }
    return stylename;
  }

  private Set<String> getMatchStyleNames() {
    Set<String> styleNames = new HashSet<String>();
    String sname;
    HashMap<String, OdfDefaultStyle> defaultStyles = new HashMap<String, OdfDefaultStyle>();
    try {
      NodeList defStyleList = mTextDocument.getDocumentStyles().getElementsByTagName("style:default-style");
      for (int i = 0; i < defStyleList.getLength(); i++) {
        OdfDefaultStyle defStyle = (OdfDefaultStyle) defStyleList.item(i);
        defaultStyles.put(defStyle.getFamilyName(), defStyle);
      }
      NodeList styleList = mTextDocument.getDocumentStyles().getElementsByTagName("style:style");
      for (int i = 0; i < styleList.getLength(); i++) {
        OdfStyle sStyle = (OdfStyle) styleList.item(i);
        // get default properties and style properties
        Map<OdfStyleProperty, String> map = sStyle.getStylePropertiesDeep();
        // check if properties include all search properties and value
        // equal
        Iterator<OdfStyleProperty> pIter = mProps.keySet().iterator();
        boolean isStyle = false;
        while (pIter.hasNext()) {
          isStyle = false;
          OdfStyleProperty p = pIter.next();
          if (map.containsKey(p)) {
            if (map.get(p).equals(mProps.get(p))) {
              isStyle = true;
            } else {
              break;
            }
          } else {
            break;
          }
        }
        // put all match style names
        if (isStyle) {
          sname = sStyle.getStyleNameAttribute();
          // if(sname.contains("default"))sname="defaultstyle";
          styleNames.add(sname);
        }
      }
      // get all automatic styles
      Iterator<OdfStyle> cStyles = mTextDocument.getContentDom().getAutomaticStyles().getAllStyles().iterator();
      while (cStyles.hasNext()) {
        OdfStyle cStyle = cStyles.next();
        // get default properties and style properties
        Map<OdfStyleProperty, String> map = cStyle.getStylePropertiesDeep();

        if (cStyle.getParentStyle() == null) {
          if (cStyle.getFamilyName().equals("text")) {
            if (defaultStyles.containsKey("text")) {
              getTextDefaultProperties("text", defaultStyles, map);
            } else {
              getTextDefaultProperties("paragraph", defaultStyles, map);
            }
          }
        }
        // check if the search properties is in properties
        Iterator<OdfStyleProperty> pIter = mProps.keySet().iterator();
        boolean isStyle = false;
        while (pIter.hasNext()) {
          isStyle = false;
          OdfStyleProperty p = pIter.next();
          if (map.containsKey(p)) {
            if (map.get(p).equals(mProps.get(p))) {
              isStyle = true;
            } else {
              break;
            }
          } else {
            break;
          }
        }
        // put all match style names
        if (isStyle) {
          styleNames.add(cStyle.getStyleNameAttribute());
        }
      }
    } catch (Exception e1) {
      Logger.getLogger(TextStyleNavigation.class.getName()).log(Level.SEVERE, e1.getMessage(), e1);
    }
    return styleNames;
  }

  private void getTextDefaultProperties(String familyName, HashMap<String, OdfDefaultStyle> defaultStyles,
      Map<OdfStyleProperty, String> map) {
    OdfDefaultStyle defStyle = defaultStyles.get(familyName);
    if (defStyle != null) {
      OdfStyleFamily family = defStyle.getFamily();
      if (family != null) {
        for (OdfStyleProperty property : family.getProperties()) {
          if (!map.containsKey(property) && defStyle.hasProperty(property)) {
            map.put(property, defStyle.getProperty(property));
          }
        }
      }
    }
  }
}
TOP

Related Classes of org.odftoolkit.simple.common.navigation.TextStyleNavigation

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.