/*******************************************************************************
 * Copyright (c) 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.ui.internal.intro.impl.html;
import java.io.*;
import java.net.*;

import org.eclipse.ui.internal.intro.impl.*;
import org.eclipse.ui.internal.intro.impl.model.*;
import org.eclipse.ui.internal.intro.impl.util.*;
public class IntroHTMLGenerator {
	private AbstractIntroPage introPage;
	
	/**
	 * Generates the HTML code that will be presented in the browser widget for
	 * the provided intro page.
	 * 
	 * @param page
	 *            the page to generate HTML for
	 * @param title
	 *            the title of the intro presentation, or null
	 */
	public HTMLElement generateHTMLforPage(AbstractIntroPage page) {
		if (page == null)
			return null;
		this.introPage = page;
		// generate and add the appropriate encoding to the top of the document
		// generateEncoding();
		// create the main HTML element, and all of its contents
		return generateHTMLElement();
	}
	private HTMLElement generateEncoding() {
		HTMLElement encoding = new HTMLElement(""); //$NON-NLS-1$
		// TODO: figure out how to handle locale based encoding
		// As far as the HTML generator is concerned, this is probably as
		// simple as asking the model for the information
		return encoding;
	}
	/**
	 * Generates the HTML element and its content:
	 * 
	 * <pre>
	 * 
	 *     &lt;HTML&gt;
	 *     &lt;HEAD&gt;
	 *     head content
	 *     &lt;/HEAD&gt;
	 *     &lt;BODY&gt;
	 *     body content
	 *     &lt;/BODY&gt;
	 *     &lt;/HTML&gt;
	 *
	 * </pre>
	 * 
	 * @return the html HTMLElement
	 */
	private HTMLElement generateHTMLElement() {
		// this is the outermost element, so it has no indent
		int indentLevel = 0;
		HTMLElement html = new FormattedHTMLElement(
				IIntroHTMLConstants.ELEMENT_HTML, indentLevel, true);
		HTMLElement head = generateHeadElement(indentLevel + 1);
		HTMLElement body = generateBodyElement(indentLevel + 1);
		html.addContent(head);
		html.addContent(body);
		return html;
	}
	/**
	 * Generates the HEAD element and its content:
	 * 
	 * <pre>
	 * 
	 *     &lt;HEAD&gt;
	 *     &lt;BASE href=&quot;base_plugin_location&gt;
	 *     &lt;style type=&quot;text/css&quot;&gt;HTML, IMG { border: 0px; } &lt;/style&gt;
	 *     &lt;TITLE&gt;page title &lt;/TITLE&gt;
	 *     &lt;LINK href=&quot;style sheet&quot;&gt;
	 *     additional head content, if specified
	 *     &lt;/HEAD&gt;
	 *  
	 * </pre>
	 * 
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is
	 *            printed
	 * @return the head HTMLElement
	 */
	private HTMLElement generateHeadElement(int indentLevel) {
		HTMLElement head = new FormattedHTMLElement(
				IIntroHTMLConstants.ELEMENT_HEAD, indentLevel, true);
		// add the title
		head.addContent(generateTitleElement(null, indentLevel + 1));
		// create the BASE element
		String basePath = HTMLUtil.getResolvedBundleLocation(introPage
				.getBundle());
		HTMLElement base = generateBaseElement(indentLevel + 1, basePath);
		if (base != null)
			head.addContent(base);
		// create the HTML style block
		head.addContent(generateStyleElement(indentLevel + 1));
		// add the presentation style
		String style = IntroPlugin.getDefault().getIntroModelRoot()
				.getPresentation().getImplementationStyle();
		if (style != null)
			head.addContent(generateLinkElement(style, indentLevel + 1));
		//TODO: Should introPage.getStyles() return the main page style as
		// well?
		style = introPage.getStyle();
		if (style != null)
			head.addContent(generateLinkElement(style, indentLevel + 1));
		// add the page's inherited style(s)
		String[] pageStyles = introPage.getStyles();
		for (int i = 0; i < pageStyles.length; i++) {
			style = pageStyles[i];
			if (style != null)
				head.addContent(generateLinkElement(style, indentLevel + 1));
		}
		// if there is additional head conent specified in an external file,
		// include it. Additional head content can be specified at the
		// implementation level (which would apply to ALL pages) and at the
		// page level (which would apply only to that particular page).
		// For the implementation's head contribution:
		StringBuffer content = null;
		IntroHead introHead = IntroPlugin.getDefault().getIntroModelRoot()
				.getPresentation().getHead();
		if (introHead != null) {
			content = readFromFile(introHead.getSrc());
			if (content != null)
				head.addContent(content);
		}
		// For the page's head contribution:
		// TODO: there should only be one of these at the page level, not a
		// collection..
		IntroHead[] htmlHeads = introPage.getHTMLHeads();
		for (int i = 0; i < htmlHeads.length; i++) {
			introHead = htmlHeads[i];
			if (introHead != null) {
				content = readFromFile(introHead.getSrc());
				if (content != null)
					head.addContent(content);
			}
		}
		return head;
	}
	/**
	 * Generates the BODY element and its content:
	 * 
	 * <pre>
	 * 
	 *     &lt;BODY&gt;
	 *     &lt;DIV id=&quot;pageId&quot; class=&quot;pageClass&quot;&gt;
	 *     page content
	 *     &lt;/DIV&gt;
	 *     &lt;/BODY&gt;
	 *
	 * </pre>
	 * 
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is
	 *            printed
	 * @return the body HTMLElement
	 */
	private HTMLElement generateBodyElement(int indentLevel) {
		HTMLElement body = new FormattedHTMLElement(
				IIntroHTMLConstants.ELEMENT_BODY, indentLevel, true);
		// Create the div that contains the page content
		String pageId = (introPage.getId() != null)
				? introPage.getId()
				: IIntroHTMLConstants.DIV_ID_PAGE;
		HTMLElement pageContentDiv = generateDivElement(pageId, indentLevel + 1);
		if (introPage.getStyleId() != null)
			pageContentDiv.addAttribute(IIntroHTMLConstants.ATTRIBUTE_CLASS,
					introPage.getStyleId());
		// Add any children of the page, in the order they are defined
		AbstractIntroElement[] children = introPage.getChildren();
		for (int i = 0; i < children.length; i++) {
			AbstractIntroElement child = children[i];
			// check to see if this element should be filtered from the HTML 
			// presentation
			if(!filteredFromPresentation(child)){
				// use indentLevel + 2 here, since this element is contained within
				// the pageContentDiv
				HTMLElement childElement = generateIntroElement(child,
						indentLevel + 2);
				if (childElement != null)
					pageContentDiv.addContent(childElement);
			}
		}
		body.addContent(pageContentDiv);
		return body;
	}
	/**
	 * Given an IntroElement, generate the appropriate HTMLElement
	 * 
	 * @param element
	 *            the IntroElement
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is
	 *            printed
	 * @return an HTMLElement
	 */
	private HTMLElement generateIntroElement(AbstractIntroElement element,
			int indentLevel) {
		if (element == null)
			return null;
		switch (element.getType()) {
			case AbstractIntroElement.GROUP :
				return generateIntroDiv((IntroGroup) element, indentLevel);
			case AbstractIntroElement.LINK :
				return generateIntroLink((IntroLink) element, indentLevel);
			case AbstractIntroElement.HTML :
				return generateIntroHTML((IntroHTML) element, indentLevel);
			case AbstractIntroElement.IMAGE :
				return generateIntroImage((IntroImage) element, indentLevel);
			case AbstractIntroElement.TEXT :
				return generateIntroText((IntroText) element, indentLevel);
			case AbstractIntroElement.PAGE_TITLE :
				return generateIntroTitle((IntroPageTitle) element, indentLevel);
			default :
				return null;
		}
	}
	/**
	 * Create a div element and its content from an IntroDiv:
	 * 
	 * <pre>
	 * 
	 *     &lt;div id=&quot;attrvalue&quot;&gt;
	 *     &lt;h4&gt;&lt;span class=&quot;div-label&quot;&gt;attrvalue&lt;/span&gt;&lt;h4&gt;
	 *     any defined divs, links, html, images, text, includes
	 *     &lt;/div&gt;
	 *  
	 * </pre>
	 * 
	 * @param element
	 *            the IntroDiv
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is
	 *            printed
	 * @return a div HTMLElement
	 */
	private HTMLElement generateIntroDiv(IntroGroup element, int indentLevel) {
		// Create the outer div element
		HTMLElement divElement = generateDivElement(element.getId(),
				indentLevel);
		// if a div class was specified, add it
		if (element.getStyleId() != null)
			divElement.addAttribute(IIntroHTMLConstants.ATTRIBUTE_CLASS,
					element.getStyleId());
		// Create the div label, if specified
		if (element.getLabel() != null) {
			HTMLElement divLabel = generateTextElement(
					IIntroHTMLConstants.ELEMENT_H4, null,
					IIntroHTMLConstants.SPAN_CLASS_DIV_LABEL, element
							.getLabel(), indentLevel + 1);
			divElement.addContent(divLabel);
		}
		// Add any children of the div, in the order they are defined
		AbstractIntroElement[] children = element.getChildren();
		for (int i = 0; i < children.length; i++) {
			AbstractIntroElement child = children[i];
			HTMLElement childElement = generateIntroElement(child,
					indentLevel + 1);
			if (childElement != null)
				divElement.addContent(childElement);
		}
		return divElement;
	}
	/**
	 * Generates an anchor (link) element and its content from an IntroLink:
	 * 
	 * <pre>
	 * 
	 *     &lt;A id=linkId class=&quot;link&quot; href=linkHref&gt;
	 *     &lt;IMG src=&quot;blank.gif&quot;&gt;
	 *     &lt;SPAN class=&quot;link-label&quot;&gt;linkLabel &lt;/SPAN&gt;
	 *     &lt;P&gt;&lt;SPAN&gt;text&lt;/SPAN&gt;&lt;/P&gt;
	 *     &lt;/A&gt;
	 *  
	 * </pre>
	 * 
	 * @param element
	 *            the IntroLink
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is
	 *            printed
	 * @return an anchor (&lt;A&gt;) HTMLElement
	 */
	private HTMLElement generateIntroLink(IntroLink element, int indentLevel) {
		HTMLElement anchor = generateAnchorElement(element, indentLevel);
		// add <IMG src="blank.gif">
		String blankImageURL = IntroModelRoot.getPluginLocation(
				IIntroHTMLConstants.IMAGE_SRC_BLANK, IIntroConstants.PLUGIN_ID);
		if (blankImageURL != null) {
			anchor.addContent(generateImageElement(blankImageURL, null, 
					IIntroHTMLConstants.IMAGE_CLASS_BG,	indentLevel + 1));
		}
		// add link image, if one is specified
		if(element.getImg() != null) {
			HTMLElement img = generateIntroImage(element.getImg(), indentLevel + 1);
			anchor.addContent(img);
		}
		// add <SPAN class="link-label">linkLabel</SPAN>
		if (element.getLabel() != null) {
			HTMLElement label = generateSpanElement(
					IIntroHTMLConstants.SPAN_CLASS_LINK_LABEL, indentLevel + 1);
			label.addContent(element.getLabel());
			anchor.addContent(label);
		}
		IntroText linkText = element.getIntroText();
		if (linkText != null && linkText.getText() != null) {
			String classId = (linkText.getStyleId() != null) ? linkText
					.getStyleId() : IIntroHTMLConstants.SPAN_CLASS_TEXT;
			HTMLElement text = generateTextElement(
					IIntroHTMLConstants.ELEMENT_PARAGRAPH, linkText.getId(),
					classId, element.getText(), indentLevel + 1);
			anchor.addContent(text);
		}
		return anchor;
	}
	/**
	 * Generate the appropriate HTML from an IntroHTML. If the IntroHTML type is
	 * "inline", then the content from the referenced file is emitted as-is into
	 * a div element. If the type is "embed", an OBJECT html element is created
	 * whose <code>data</code> attribute is equal to the IntroHTML's
	 * <code>src</code> value
	 * 
	 * @param element
	 *            the IntroHTML
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is
	 *            printed
	 * @return an HTMLElement
	 */
	private HTMLElement generateIntroHTML(IntroHTML element, int indentLevel) {
		if (element.isInlined())
			return generateInlineIntroHTML(element, indentLevel);
		else
			return generateEmbeddedIntroHTML(element, indentLevel);
	}
	/**
	 * Generate an image element from an IntroImage:
	 * 
	 * <pre>
	 * 
	 *     &lt;IMG src=imageSrc id=imageId&gt;
	 *  
	 * </pre>
	 * 
	 * @param element
	 *            the IntroImage
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is
	 *            printed
	 * @return an img HTMLElement
	 */
	private HTMLElement generateIntroImage(IntroImage element, int indentLevel) {
		HTMLElement imageElement = generateImageElement(element.getSrc(),
				element.getAlt(), element.getStyleId(), indentLevel);
		if (element.getId() != null)
			imageElement.addAttribute(IIntroHTMLConstants.ATTRIBUTE_ID, element
					.getId());
		return imageElement;
	}
	/**
	 * Generate a paragraph (&lt;P&gt;) element from an IntroText. The paragraph
	 * element will contain a span element that will contain the actual text.
	 * Providing the span element provides additional flexibility for CSS
	 * designers.
	 * 
	 * <pre>
	 * 
	 *     &lt;P&gt;&lt;SPAN&gt;spanContent&lt;/SPAN&gt;&lt;/P&gt;
	 *  
	 * </pre>
	 * 
	 * @param element
	 *            the IntroText
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is
	 *            printed
	 * @return a paragraph HTMLElement
	 */
	private HTMLElement generateIntroText(IntroText element, int indentLevel) {
		String spanClass = (element.getStyleId() != null) ? element
				.getStyleId() : IIntroHTMLConstants.SPAN_CLASS_TEXT;
		HTMLElement textElement = generateTextElement(
				IIntroHTMLConstants.ELEMENT_PARAGRAPH, element.getId(),
				spanClass, element.getText(), indentLevel);
		return textElement;
	}
	/**
	 * @param element
	 * @param indentLevel
	 * @return
	 */
	private HTMLElement generateIntroTitle(IntroPageTitle element,
			int indentLevel) {
		HTMLElement titleElement = generateHeaderDiv(element.getId(), element
				.getStyleId(), IIntroHTMLConstants.ELEMENT_H1, element
				.getTitle(), indentLevel);
		return titleElement;
	}
	/**
	 * Generate "inline" content from an IntroHTML. The content from the file
	 * referenced by the IntroHTML's <code>src</code> attribute is emitted
	 * as-is into a div element:
	 * 
	 * <pre>
	 * 
	 *     &lt;div id=&quot;attrvalue&quot; class=&quot;attrvalue2&quot;&gt;
	 *     content from file specified in src attribute
	 *     &lt;/div&gt;
	 *  
	 * </pre>
	 * 
	 * @param element
	 *            the IntroHTML
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is
	 *            printed
	 * @return a div HTMLElement, or null if there was a problem reading from
	 *         the file
	 */
	private HTMLElement generateInlineIntroHTML(IntroHTML element,
			int indentLevel) {
		StringBuffer content = readFromFile(element.getSrc());
		if (content != null && content.length() > 0) {
			// Create the outer div element
			String divClass = (element.getStyleId() != null) ? element
					.getStyleId() : IIntroHTMLConstants.DIV_CLASS_INLINE_HTML;
			HTMLElement divElement = generateDivElement(element.getId(),
					divClass, indentLevel);
			// add the content of the specified file into the div element
			divElement.addContent(content);
			return divElement;
		}
		return null;
	}
	/**
	 * Generate "embedded" content from an IntroHTML. An OBJECT html element is
	 * created whose <code>data</code> attribute is equal to the IntroHTML's
	 * <code>src</code> value.
	 * 
	 * <pre>
	 * 
	 *     &lt;OBJECT type=&quot;text/html&quot; data=&quot;attrvalue&quot;&gt;
	 *     alternative text in case the object can not be rendered
	 *     &lt;/OBJECT&gt; 
	 *  
	 * </pre>
	 * 
	 * @param element
	 *            the IntroHTML
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is
	 *            printed
	 * @return an object HTMLElement
	 */
	private HTMLElement generateEmbeddedIntroHTML(IntroHTML element,
			int indentLevel) {
		HTMLElement objectElement = new FormattedHTMLElement(
				IIntroHTMLConstants.ELEMENT_OBJECT, indentLevel, true);
		objectElement.addAttribute(IIntroHTMLConstants.ATTRIBUTE_TYPE,
				IIntroHTMLConstants.OBJECT_TYPE);
		if (element.getId() != null)
			objectElement.addAttribute(IIntroHTMLConstants.ATTRIBUTE_ID,
					element.getId());
		if (element.getSrc() != null)
			objectElement.addAttribute(IIntroHTMLConstants.ATTRIBUTE_DATA,
					element.getSrc());
		if (element.getStyleId() != null)
			objectElement.addAttribute(IIntroHTMLConstants.ATTRIBUTE_CLASS,
					element.getStyleId());
		// The alternative content is added in case the browser can not render
		// the specified content
		IntroText htmlText = element.getIntroText();
		if (htmlText != null && htmlText.getText() != null) {
			String textClass = (htmlText.getStyleId() != null) ? htmlText
					.getStyleId() : IIntroHTMLConstants.SPAN_CLASS_TEXT;
			HTMLElement text = generateTextElement(
					IIntroHTMLConstants.ELEMENT_PARAGRAPH, htmlText.getId(),
					textClass, element.getText(), indentLevel);
			if (text != null)
				objectElement.addContent(text);
		}
		if (element.getIntroImage() != null) {
			HTMLElement img = generateIntroImage(element.getIntroImage(),
					indentLevel);
			if (img != null)
				objectElement.addContent(img);
		}
		return objectElement;
	}
	/**
	 * Generates the BASE element for the head of the html document. Each
	 * document can have only one base element
	 * 
	 * <pre>
	 *   	&lt;BASE href=baseURL&gt;
	 * </pre>
	 * 
	 * @param indentLevel
	 * @param baseURL
	 * @return
	 */
	private HTMLElement generateBaseElement(int indentLevel, String baseURL) {
		HTMLElement base = new FormattedHTMLElement(
				IIntroHTMLConstants.ELEMENT_BASE, indentLevel, true, false);
		if (baseURL != null)
			base.addAttribute(IIntroHTMLConstants.ATTRIBUTE_HREF, baseURL);
		return base;
	}
	/**
	 * Generates the style element that goes into HEAD:
	 * 
	 * <pre>
	 * 
	 *     &lt;style type=&quot;text/css&quot;&gt;HTML, IMG { border: 0px; } &lt;/style&gt;
	 *
	 * </pre>
	 * 
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is
	 *            printed
	 * @return the style HTMLElement
	 */
	private HTMLElement generateStyleElement(int indentLevel) {
		HTMLElement style = new FormattedHTMLElement(
				IIntroHTMLConstants.ELEMENT_STYLE, indentLevel, false);
		style.addAttribute(IIntroHTMLConstants.ATTRIBUTE_TYPE,
				IIntroHTMLConstants.LINK_STYLE);
		style.addContent(IIntroHTMLConstants.STYLE_HTML);
		return style;
	}
	/**
	 * Generates the title element and its content:
	 * 
	 * <pre>
	 * 
	 *     &lt;TITLE&gt;intro title&lt;/TITLE&gt;
	 *  
	 * </pre>
	 * 
	 * @param title
	 *            the title of this intro page
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is
	 *            printed
	 * @return the title HTMLElement
	 */
	private HTMLElement generateTitleElement(String title, int indentLevel) {
		HTMLElement titleElement = new FormattedHTMLElement(
				IIntroHTMLConstants.ELEMENT_TITLE, indentLevel, false);
		if (title != null)
			titleElement.addContent(title);
		return titleElement;
	}
	/**
	 * Generates a link element that refers to a cascading style sheet (CSS):
	 * 
	 * <pre>
	 * 
	 *     &lt;LINK rel=&quot;stylesheet&quot; style=&quot;text/css&quot; href=&quot;style sheet&quot;&gt;
	 *  
	 * </pre>
	 * 
	 * @param href
	 *            the value of the href attribute for this link element
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is
	 *            printed
	 * @return a link HTMLElement
	 */
	private HTMLElement generateLinkElement(String href, int indentLevel) {
		HTMLElement link = new FormattedHTMLElement(
				IIntroHTMLConstants.ELEMENT_LINK, indentLevel, true, false);
		link.addAttribute(IIntroHTMLConstants.ATTRIBUTE_RELATIONSHIP,
				IIntroHTMLConstants.LINK_REL);
		link.addAttribute(IIntroHTMLConstants.ATTRIBUTE_STYLE,
				IIntroHTMLConstants.LINK_STYLE);
		if (href != null)
			link.addAttribute(IIntroHTMLConstants.ATTRIBUTE_HREF, href);
		return link;
	}
	/**
	 * Generate an anchor element:
	 * 
	 * <pre>
	 * 
	 *     &lt;A id=linkId class=linkClass href=linkHref&gt; &lt;/A&gt;
	 *  
	 * </pre>
	 * 
	 * @param link
	 *            the IntroLink element that contains the value for the id and
	 *            href attributes
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is
	 *            printed
	 * @return an anchor (&lt;A&gt;) HTMLElement
	 */
	private HTMLElement generateAnchorElement(IntroLink link, int indentLevel) {
		HTMLElement anchor = new FormattedHTMLElement(
				IIntroHTMLConstants.ELEMENT_ANCHOR, indentLevel, true);
		if (link.getId() != null)
			anchor.addAttribute(IIntroHTMLConstants.ATTRIBUTE_ID, link.getId());
		if (link.getUrl() != null)
			anchor.addAttribute(IIntroHTMLConstants.ATTRIBUTE_HREF, link
					.getUrl());
		if (link.getStyleId() != null)
			anchor.addAttribute(IIntroHTMLConstants.ATTRIBUTE_CLASS, link
					.getStyleId());
		else
			anchor.addAttribute(IIntroHTMLConstants.ATTRIBUTE_CLASS,
					IIntroHTMLConstants.ANCHOR_CLASS_LINK);
		return anchor;
	}
	/**
	 * Generates a div block that contains a header and span element:
	 * 
	 * <pre>
	 *   
	 *     &lt;DIV id=divId&gt;
	 *     &lt;H&gt;&lt;SPAN&gt;spanContent &lt;/SPAN&gt; &lt;/H&gt;
	 *     &lt;/DIV&gt;
	 *  
	 * </pre>
	 * 
	 * @param divId
	 *            the id of the div to create
	 * @param divClass
	 *            the class of the div
	 * @param headerType
	 *            what type of header to create (e.g., H1, H2, etc)
	 * @param spanContent
	 *            the span content
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is
	 *            printed
	 * @return a div HTMLElement that contains a header
	 */
	private HTMLElement generateHeaderDiv(String divId, String divClass,
			String headerType, String spanContent, int indentLevel) {
		// create the text element: <P><SPAN>spanContent</SPAN></P>
		HTMLElement text = generateTextElement(headerType, null, null,
				spanContent, indentLevel + 1);
		// create the containing div element
		HTMLElement div = generateDivElement(divId, divClass, indentLevel);
		div.addContent(text);
		return div;
	}
	/**
	 * Generates a span element inside a text element, where the text element
	 * can be a P (paragraph), or any of the H (Header) elements. Providing the
	 * span element provides additional flexibility for CSS designers.
	 * 
	 * <pre>
	 *   
	 *     &lt;P&gt;&lt;SPAN&gt;spanContent&lt;/SPAN&gt;&lt;/P&gt;
	 *  
	 * </pre>
	 * 
	 * @param type
	 *            the type of text element to create (e.g., P, H1, H2, etc)
	 * @param spanID
	 *            the id of the span element, or null
	 * @param spanClass
	 *            the class of the span element, or null
	 * @param spanContent
	 *            the span content
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is
	 *            printed
	 * @return a text HTMLElement that contains a span element
	 */
	private HTMLElement generateTextElement(String type, String spanID,
			String spanClass, String spanContent, int indentLevel) {
		// Create the span: <SPAN>spanContent</SPAN>
		HTMLElement span = new HTMLElement(IIntroHTMLConstants.ELEMENT_SPAN);
		if (spanID != null)
			span.addAttribute(IIntroHTMLConstants.ATTRIBUTE_ID, spanID);
		if (spanClass != null)
			span.addAttribute(IIntroHTMLConstants.ATTRIBUTE_CLASS, spanClass);
		if (spanContent != null)
			span.addContent(spanContent);
		// Create the enclosing text element: <P><SPAN>spanContent</SPAN></P>
		HTMLElement text = new FormattedHTMLElement(type, indentLevel, false);
		text.addContent(span);
		return text;
	}
	/**
	 * Generates a DIV element with the provided indent, id, and class.
	 * 
	 * @param divId
	 *            value for the div's id attribute
	 * @param divClass
	 *            value for the div's class attribute
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is
	 *            printed
	 * @return a div HTMLElement
	 */
	private HTMLElement generateDivElement(String divId, String divClass,
			int indentLevel) {
		HTMLElement div = generateDivElement(divId, indentLevel);
		div.addAttribute(IIntroHTMLConstants.ATTRIBUTE_CLASS, divClass);
		return div;
	}
	/**
	 * Generates a DIV element with the provided indent and id.
	 * 
	 * @param divId
	 *            value for the div's id attribute
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is
	 *            printed
	 * @return a div HTMLElement
	 */
	private HTMLElement generateDivElement(String divId, int indentLevel) {
		HTMLElement div = new FormattedHTMLElement(
				IIntroHTMLConstants.ELEMENT_DIV, indentLevel, true);
		if (divId != null)
			div.addAttribute(IIntroHTMLConstants.ATTRIBUTE_ID, divId);
		return div;
	}
	/**
	 * Generates an IMG element:
	 * 
	 * <pre>
	 *   
	 *     &lt;IMG src=imageSrc alt=altText&gt;
	 *  
	 * </pre>
	 * 
	 * @param imageSrc
	 *            the value to be supplied to the src attribute
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is
	 *            printed
	 * @return an img HTMLElement
	 */
	private HTMLElement generateImageElement(String imageSrc, String altText,
			String imageClass, int indentLevel) {
		HTMLElement image = new FormattedHTMLElement(
				IIntroHTMLConstants.ELEMENT_IMG, indentLevel, true, false);
		image.addAttribute(IIntroHTMLConstants.ATTRIBUTE_SRC, imageSrc);
		if (altText == null)
			altText = ""; //$NON-NLS-1$
		image.addAttribute(IIntroHTMLConstants.ATTRIBUTE_ALT, altText);
		if(imageClass != null)
				image.addAttribute(IIntroHTMLConstants.ATTRIBUTE_CLASS, imageClass);
		return image;
	}
	/**
	 * Generate a span element
	 * 
	 * <pre>
	 * 
	 *     &lt;SPAN class=spanClass&gt; &lt;/SPAN&gt;
	 *  
	 * </pre>
	 * 
	 * @param spanClass
	 *            the value to be supplied to the class attribute
	 * @param indentLevel
	 *            the number of indents to insert before the element when it is
	 *            printed
	 * @return a span HTMLElement
	 */
	private HTMLElement generateSpanElement(String spanClass, int indentLevel) {
		HTMLElement span = new FormattedHTMLElement(
				IIntroHTMLConstants.ELEMENT_SPAN, indentLevel, false);
		span.addAttribute(IIntroHTMLConstants.ATTRIBUTE_CLASS, spanClass);
		return span;
	}
	
    private boolean filteredFromPresentation(AbstractIntroElement element) {
        if (element.isOfType(AbstractIntroElement.BASE_ELEMENT))
            return ((AbstractBaseIntroElement) element).isFiltered();
        else
            return false;
    }
    
	
	/**
	 * Reads the content of the file referred to by the <code>src</code>
	 * parameter and returns the content in the form of a StringBuffer.
	 * If the file read contains substitution segments of the form
	 * $plugin:plugin_id$ then this method will make the proper 
	 * substitution (the segment will be replaced with the absolute 
	 * path to the plugin with id plugin_id).
	 * 
	 * @param src -
	 *            the file that contains the target conent
	 * @return a StringBuffer containing the content in the file, or null
	 */
	private StringBuffer readFromFile(String src) {
		if (src == null)
			return null;
		InputStream stream = null;
		StringBuffer content = new StringBuffer();
		BufferedReader reader = null;
		try {
			URL url = new URL(src);
			stream = url.openStream();
			//TODO: Do we need to worry about the encoding here? e.g.:
			//reader = new BufferedReader(new InputStreamReader(stream,
			// ResourcesPlugin.getEncoding()));
			reader = new BufferedReader(new InputStreamReader(stream));
			while (true) {	
				int character = reader.read();
				if (character == -1) // EOF
					break; // done reading file
				
				else if(character == PluginIdParser.SUBSTITUTION_BEGIN) { // possible substitution
					PluginIdParser parser = new PluginIdParser(character, reader);
					// If a valid plugin id was found in the proper format, text 
					// will be the absolute path to that plugin. Otherwise, text
					// will simply be all characters read up to (but not including)
					// the next dollar sign that follows the one just found.
					String text = parser.parsePluginId();
					if(text != null)
						content.append(text);		
				}
				else {
					// make sure character is in char range before making cast
					if(character > 0x00 && character < 0xffff) 
						content.append((char)character);
					else content.append(character);
				}
			}
		} catch (Exception exception) {
			Log.error("Error reading from file", exception); //$NON-NLS-1$
		} finally {
			try {
				if (reader != null)
					reader.close();
				if (stream != null)
					stream.close();
			} catch (IOException e) {
				Log.error("Error closing input stream", e); //$NON-NLS-1$
				return null;
			}
		}
		return content;
	}
	
	/**
	 * A helper class to help identify substitution strings in a content file.
	 * A properly formatted substitution string is of the form:
	 *   <code>$plugin:plugin_id$</code>
	 * where plugin_id is the valid id of an installed plugin. The substitution
	 * string will be replaced with the absolute path to the plugin.  
	 * 
	 * An example usage of the string substution:
	 * The html file <code>inline.html</code> is included in your intro via 
	 * the html inline mechanism .  This file needs to reference a resource that 
	 * is located in another plugin.  The following might be found in inline.html: 
	 * <code>
	 *    <a href="$plugin:test.plugin$html/test.html">link to file</a>
	 * </code>
	 * When this file is read in, the relevant section will be replaced as follows:
	 * <code>
	 *   <a href="file:/install_path/plugins/test.plugin/html/test.html">link to file</a>
	 * </code>
	 * 
	 */
	private static class PluginIdParser {
		private BufferedReader reader;
		private static final char SUBSTITUTION_BEGIN = '$';
		private static final char SUBSTITUTION_END = '$';
		// tokenContent will contain all characters read by the parser, starting 
		// with and including the initial $ token.   
		private StringBuffer tokenContent;
		// pluginId will contain the content between the "$plugin:" segment
		// and the closing "$" token
		private StringBuffer pluginId;
		
		protected PluginIdParser(char tokenBegin, BufferedReader bufferedreader){
			reader = bufferedreader;
			tokenContent = new StringBuffer(tokenBegin);
			pluginId = new StringBuffer();
		}
		
		protected PluginIdParser(int tokenBegin, BufferedReader bufferedreader){
			reader = bufferedreader;
			tokenContent = new StringBuffer();
			pluginId = new StringBuffer();
			// make sure tokenBegin is in char range before making cast
			if(tokenBegin > 0x00 && tokenBegin < 0xffff) 
				tokenContent.append((char)tokenBegin);
		}
			
		/**
		 * This method should be called after the initial substitution identifier
		 * has been read in (the substition string begins and ends with the "$"
		 * character).  
		 * A properly formatted substitution string is of the form:
		 *   </code>"$plugin:plugin_id$</code>
		 * - the initial "$" is immediately followed by the "plugin:" segment
		 * - the <code>plugin_id</code> refers to a valid, installed plugin
		 * - the substitution string is terminated by a closing "$"
		 * If the above conditions are not met, no substitution occurs.
		 * If the above conditions are met, the content between (and including)
		 * the opening and closing "$" characters will be replaced by the
		 * absolute path to the plugin
		 * @return
		 */
		protected String parsePluginId() {
			if(reader == null || tokenContent == null || pluginId == null)
				return null;
			
			try {
				// Mark the current position of the reader so we can roll
				// back to this point if the proper "plugin:" segment is not found.
				// Use 1024 as our readAheadLimit
				reader.mark(0x400);
				if(findValidPluginSegment()){
					String pluginPath = getPluginPath();
					if(pluginPath == null){
						// Didn't find a valid plugin id.
						// return tokenContent, which contains all characters
						// read up to (not including) the last $. (if the
						// last $ is part of a subsequent "$plugin:" segment 
						// it can still be processed properly)
						return tokenContent.toString();
					}
					else {
						return pluginPath;
					}
				} 
				else {
					// The "plugin:" segment was not found.  Reset the reader 
					// so we can continue reading character by character.
					reader.reset();
					return tokenContent.toString();
				}
				
			} catch (IOException exception){
				Log.error("Error reading from file", exception); //$NON-NLS-1$
				return tokenContent.toString();
			}
		}
		
		/**
		 * This method should be called after an initial substitution character
		 * has been found (that is, after a $).  It looks at the subsequent  
		 * characters in the input stream to determine if they match the 
		 * expected <code>plugin:</code> segment of the substitution string.
		 * If the expected characters are found, they will be appended to the
		 * tokenContent StringBuffer and the method will return true.  If they
		 * are not found, false is returned and the caller should reset the
		 * BufferedReader to the position it was in before this method was called.
		 * 
		 * Resetting the reader ensures that the characters read in this method
		 * can be re-examined in case one of them happens to be the beginning of
		 * a valid substitution segment.
		 * 
		 * @return true if the next characters match <code>plugin:</code>, and 
		 * false otherwise.
		 */
		private boolean findValidPluginSegment(){
			final char[] PLUGIN_SEGMENT = {'p', 'l', 'u', 'g', 'i', 'n', ':' };
			char[] streamContent = new char[PLUGIN_SEGMENT.length];
			try {
				int peek = reader.read(streamContent, 0, PLUGIN_SEGMENT.length);
				if ((peek == PLUGIN_SEGMENT.length) 
						&& (HTMLUtil.equalCharArrayContent(streamContent, PLUGIN_SEGMENT))){
					// we have found the "$plugin:" segment
					tokenContent.append(streamContent);
					return true;
				}
				// The "plugin:" segment did not immediately follow the initial $.
				return false;
			} catch (IOException exception){
				Log.error("Error reading from file", exception); //$NON-NLS-1$
				return false;
			}
		}
		/**
		 * This method continues to read from the input stream until
		 * either the end of the file is reached, or until a character
		 * is found that indicates the end of the substitution.  If the
		 * SUBSTITUTION_END character is found, the method looks up the
		 * plugin id that has been built up to see if it is a valid
		 * id.  If so, return the absolute path to that plugin.  If not,
		 * return null.
		 * 
		 * This method assumes that the reader is positioned just 
		 * after a valid <code>plugin:</code> segment in a substitution
		 * string.
		 * 
		 * @return absolute path of the plugin id, if valid.  null otherwise
		 */
		private String getPluginPath(){
			try {
				while(true) {
					int nextChar = reader.read();
	
					if(nextChar == -1) { 
						// reached EOF while looking for closing $
						return null;
					}
					else if(nextChar == SUBSTITUTION_END) { // end of plugin id
						// look up the plugin id.  If it is a valid id 
						// return the absolute path to this plugin.
						// otherwise return null.
						String path = HTMLUtil.getResolvedBundleLocation(
								pluginId.toString());
						
						// If the plugin id was not valid, reset reader to the 
						// previous mark.  The mark should be at the character 
						// just before the last dollar sign.  
						if(path == null)
							reader.reset();
						
						return path;
					}
					else {  // we have a regular character
						// mark the most recent non-dollar char in case we don't 
						// find a valid plugin id and have to roll back
						// Use 1024 as our readAheadLimit
						reader.mark(0x400);
						// Add this character to the pluginId and tokenContent String.
						// make sure we have a valid character before performing cast
						if(nextChar > 0x00 && nextChar < 0xffff) {
							tokenContent.append((char)nextChar);
							// only include non-whitespace characters in plugin id
							if(!Character.isWhitespace((char)nextChar))
									pluginId.append((char)nextChar);
						}
						else {
							tokenContent.append(nextChar);
							pluginId.append(nextChar);
						}
					}
				}
			}  catch (IOException exception){
				Log.error("Error reading from file", exception); //$NON-NLS-1$
				return null;
			}
		}
	}
}