Package org.eclipse.help.internal.dynamic

Source Code of org.eclipse.help.internal.dynamic.ExtensionResolver

/*******************************************************************************
* Copyright (c) 2006, 2007 IBM Corporation and others.
* 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
*
* Contributors:
*     IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.help.internal.dynamic;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;

import org.eclipse.help.HelpSystem;
import org.eclipse.help.internal.HelpPlugin;
import org.eclipse.help.internal.UAElement;
import org.eclipse.help.internal.extension.ContentExtension;
import org.eclipse.help.internal.extension.ContentExtensionManager;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;

/*
* Resolves the content to use for extensions. For anchors, these are the
* nodes that will be inserted at the anchor. For replaces, these are the
* nodes that will replace the original nodes.
*/
public class ExtensionResolver {

  private static final String ELEMENT_BODY = "body"; //$NON-NLS-1$
  private static final String ATTRIBUTE_ID = "id"; //$NON-NLS-1$
 
  private DocumentProcessor processor;
  private DocumentReader reader;
  private String locale;
  private ContentExtensionManager manager;
 
  /*
   * Creates the resolver. The processor is needed to process the extension
   * content, and locale because we're pulling in content from other documents.
   */
  public ExtensionResolver(DocumentProcessor processor, DocumentReader reader, String locale) {
    this.processor = processor;
    this.reader = reader;
    this.locale = locale;
  }
 
  /*
   * Resolves the given path into nodes to be inserted.
   */
  public Node[] resolveExtension(String path, int type) {
    if (manager == null) {
      manager = HelpPlugin.getContentExtensionManager();
    }
    ContentExtension[] extensions = manager.getExtensions(path, type, locale);
    List list = new ArrayList();
    for (int i=0;i<extensions.length;++i) {
      String content = extensions[i].getContent();
      try {
        Node[] nodes = getContent(content);
        for (int j=0;j<nodes.length;++j) {
          list.add(nodes[j]);
        }
      }
      catch (Throwable t) {
        // ignore invalid extensions
      }
    }
    return (Node[])list.toArray(new Node[list.size()]);
  }
 
  /*
   * Resolves the given content path (the content to insert/replace with) into
   * nodes.
   */
  private Node[] getContent(String content) throws IOException, SAXException, ParserConfigurationException {
    String bundleId = null;
    String relativePath = null;
    String nodeId = null;
   
    int bundleStart = 0;
    // legacy; can omit leading slash
    if (content.charAt(0) == '/') {
      bundleStart = 1;
    }
    int bundleEnd = content.indexOf('/', bundleStart + 1);
    if (bundleEnd > bundleStart) {
      bundleId = content.substring(bundleStart, bundleEnd);
      int pathStart = bundleEnd + 1;
      int pathEnd = content.indexOf('#', pathStart + 1);
      if (pathEnd == -1) {
        // legacy; slash can be used instead of '#'
        int lastSlash = content.lastIndexOf('/');
        int secondLastSlash = content.lastIndexOf('/', lastSlash - 1);
        if (secondLastSlash != -1 && lastSlash > secondLastSlash) {
          String secondLastToken = content.substring(secondLastSlash + 1, lastSlash);
          if (secondLastToken.indexOf('.') != -1) {
            pathEnd = lastSlash;
          }
          else {
            pathEnd = content.length();
          }
        }
        else {
          pathEnd = content.length();
        }
      }
      relativePath = content.substring(pathStart, pathEnd);
      if (pathEnd < content.length()) {
        nodeId = content.substring(pathEnd + 1);
      }
    }
   
    if (bundleId != null && relativePath != null) {
      return getContent(bundleId, relativePath, nodeId);
    }
    return null;
  }
 
  /*
   * Resolves the given parsed content fragments into nodes.
   */
  private Node[] getContent(String bundleId, String relativePath, String nodeId) throws IOException, SAXException, ParserConfigurationException {
    String href = '/' + bundleId + '/' + relativePath;
    InputStream in = HelpSystem.getHelpContent(href, locale);
    try {
      if (nodeId != null) {
        Element element = findElement(in, nodeId);
        processor.process(new UAElement(element), href);
        return new Node[] { element };
      }
      Element body = findBody(in);
      List children = new ArrayList();
      Node node = body.getFirstChild();
      while (node != null) {
        if (node.getNodeType() == Node.ELEMENT_NODE) {
          processor.process(new UAElement((Element)node), href);
        }
        children.add(node);
        node = node.getNextSibling();
      }
      return (Node[])children.toArray(new Node[children.size()]);
    }
    finally {
      try {
        in.close();
      }
      catch (IOException e) {}
    }
  }
 
  /*
   * Finds and returns the element with the given elementId from the XML input
   * stream, or null if not found.
   */
  private Element findElement(InputStream in, String elementId) throws IOException, SAXException, ParserConfigurationException {
    return findElement(reader.read(in).element, elementId);
  }
 
  /*
   * Finds and returns the element with the given elementId from the under the
   * given element, or null if not found.
   */
  private Element findElement(Element element, String elementId) {
    String id = element.getAttribute(ATTRIBUTE_ID);
    if (id != null && id.equals(elementId)) {
      return element;
    }
    Node node = element.getFirstChild();
    while (node != null) {
      if (node.getNodeType() == Node.ELEMENT_NODE) {
        element = findElement((Element)node, elementId);
        if (element != null) {
          return element;
        }
      }
      node = node.getNextSibling();
    }
    return null;
  }
 
  /*
   * Finds and returns the body node in the given XML input.
   */
  private Element findBody(InputStream in) throws IOException, SAXException, ParserConfigurationException {
    return findBody(reader.read(in).element);
  }
 
  /*
   * Finds and returns the body node under the given node.
   */
  private Element findBody(Element element) {
    if (ELEMENT_BODY.equals(element.getNodeName())) {
      return element;
    }
    Node node = element.getFirstChild();
    while (node != null) {
      if (node.getNodeType() == Node.ELEMENT_NODE) {
        Element body = findBody((Element)node);
        if (body != null) {
          return body;
        }
      }
      node = node.getNextSibling();
    }
    return null;
  }
}
TOP

Related Classes of org.eclipse.help.internal.dynamic.ExtensionResolver

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.