/*******************************************************************************
 * Copyright (c) 2004, 2010 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
 *     Frits Jalvingh - contributions for bug 150794
 *******************************************************************************/
package org.eclipse.jst.jsp.core.internal.java;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.Externalizable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.Stack;

import javax.servlet.jsp.tagext.VariableInfo;

import org.eclipse.core.filebuffers.ITextFileBuffer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.Position;
import org.eclipse.jst.jsp.core.internal.JSPCoreMessages;
import org.eclipse.jst.jsp.core.internal.Logger;
import org.eclipse.jst.jsp.core.internal.contentmodel.TaglibController;
import org.eclipse.jst.jsp.core.internal.contentmodel.tld.TLDCMDocumentManager;
import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.JSP12TLDNames;
import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.TLDElementDeclaration;
import org.eclipse.jst.jsp.core.internal.contenttype.DeploymentDescriptorPropertyCache;
import org.eclipse.jst.jsp.core.internal.contenttype.DeploymentDescriptorPropertyCache.PropertyGroup;
import org.eclipse.jst.jsp.core.internal.provisional.JSP11Namespace;
import org.eclipse.jst.jsp.core.internal.provisional.JSP12Namespace;
import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
import org.eclipse.jst.jsp.core.internal.taglib.CustomTag;
import org.eclipse.jst.jsp.core.internal.taglib.TaglibHelper;
import org.eclipse.jst.jsp.core.internal.taglib.TaglibHelperManager;
import org.eclipse.jst.jsp.core.internal.taglib.TaglibVariable;
import org.eclipse.jst.jsp.core.internal.util.FacetModuleCoreSupport;
import org.eclipse.jst.jsp.core.internal.util.ZeroStructuredDocumentRegion;
import org.eclipse.jst.jsp.core.jspel.IJSPELTranslator;
import org.eclipse.osgi.util.NLS;
import org.eclipse.wst.html.core.internal.contentmodel.JSP20Namespace;
import org.eclipse.wst.sse.core.internal.FileBufferModelManager;
import org.eclipse.wst.sse.core.internal.ltk.parser.BlockMarker;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionCollection;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionContainer;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
import org.eclipse.wst.sse.core.utils.StringUtils;
import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
import org.eclipse.wst.xml.core.internal.parser.ContextRegionContainer;
import org.eclipse.wst.xml.core.internal.provisional.contentmodel.CMDocumentTracker;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;

import com.ibm.icu.text.MessageFormat;
import com.ibm.icu.util.StringTokenizer;

/**
 * Translates a JSP document into a HttpServlet subclass. Keeps two way mapping from
 * Java translation to the original JSP source, which can be obtained through
 * getJava2JspRanges() and getJsp2JavaRanges().
 */
public class JSPTranslator implements Externalizable {
	/**
	 * <p>This value should be incremented if any of the following methods change:
	 * <ul>
	 * <li>{@link #writeExternal(ObjectOutput)}</li>
	 * <li>{@link #readExternal(ObjectInput)}</li>
	 * <li>{@link #writeString(ObjectOutput, String)}</li>
	 * <li>{@link #readString(ObjectInput)}</li>
	 * <li>{@link #writeRanges(ObjectOutput, HashMap)}</li>
	 * <li>{@link #readRanges(ObjectInput)}</li>
	 * </ul>
	 * 
	 * This is because if any of these change then previously externalized {@link JSPTranslator}s
	 * will no longer be able to be read by the new implementation.  This value is used by
	 * the {@link Externalizable} API automatically to determine if the file being read is of the
	 * correct version to be read by the current implementation of the {@link JSPTranslator}</p>
	 * 
	 * @see #writeExternal(ObjectOutput)
	 * @see #readExternal(ObjectInput)
	 * @see #writeString(ObjectOutput, String)
	 * @see #readString(ObjectInput)
	 * @see #writeRanges(ObjectOutput, HashMap)
	 * @see #readRanges(ObjectInput)
	 */
	private static final long serialVersionUID = 1L;
	
	/** for debugging */
	private static final boolean DEBUG = Boolean.valueOf(Platform.getDebugOption("org.eclipse.jst.jsp.core/debug/jspjavamapping")).booleanValue(); //$NON-NLS-1$
	
	/** handy plugin ID constant */
	private static final String JSP_CORE_PLUGIN_ID = "org.eclipse.jst.jsp.core"; //$NON-NLS-1$
	
	// constants for reading extension point
	/** Default EL Translator extension ID */
	private static final String DEFAULT_JSP_EL_TRANSLATOR_ID = "org.eclipse.jst.jsp.defaultJSP20"; //$NON-NLS-1$
	
	/** the name of the element in the extension point */
	private static final String EL_TRANSLATOR_EXTENSION_NAME = "elTranslator"; //$NON-NLS-1$
	
	/** the name of the property in the extension point */
	private static final String ELTRANSLATOR_PROP_NAME = "ELTranslator"; //$NON-NLS-1$

	
	// these constants are commonly used strings during translation
	/** end line characters */
	public static final String ENDL = "\n"; //$NON-NLS-1$
	
	/** session variable declaration */
	private static final String SESSION_VARIABLE_DECLARATION = "javax.servlet.http.HttpSession session = pageContext.getSession();" + ENDL; //$NON-NLS-1$
	
	/** footer text */
	private static final String FOOTER = "}}"; //$NON-NLS-1$
	
	/** exception declaration */
	private static final String EXCEPTION = "Throwable exception = null;"; //$NON-NLS-1$
	
	/** expression prefix */
	public static final String EXPRESSION_PREFIX = "out.print("; //$NON-NLS-1$
	
	/** expression suffix */
	public static final String EXPRESSION_SUFFIX = ");"; //$NON-NLS-1$
	
	/** try/catch start */
	private static final String TRY_CATCH_START = ENDL + "try {" + ENDL; //$NON-NLS-1$
	
	/** try/catch end */
	private static final String TRY_CATCH_END = " } catch (java.lang.Exception e) {} " + ENDL; //$NON-NLS-1$
	
	/** JSP tag name prefix */
	static final String JSP_PREFIX = "jsp:"; //$NON-NLS-1$
	
	
	// these constants are to keep track of what type of code is currently being translated
	/** code in question is standard JSP */
	protected final static int STANDARD_JSP = 0;
	
	/** code in question is embedded (JSP as an attribute or within comment tags) */
	protected final static int EMBEDDED_JSP = 1;
	
	/** code in question is a JSP declaration */
	protected final static int DECLARATION = 2;
	
	/** code in question is a JSP expression */
	protected final static int EXPRESSION = 4;
	
	/** code in question is a JSP scriptlet */
	protected final static int SCRIPTLET = 8;
	
	
	// strings specific to this translation
	/** translated class header */
	String fClassHeader = null;
	
	/** translated class name */
	String fClassname = null;
	
	/** translated class super class */
	String fSuperclass = null;

	/** translated class imports */
	String fImplicitImports = null;

	/** translated class service header */
	String fServiceHeader = null;
	
	/** translated user defined imports */
	private StringBuffer fUserImports = new StringBuffer();
	
	//translation specific state
	/** {@link IDOMModel} for the JSP file being translated */
	IDOMModel fStructuredModel = null;
	
	/** {@link IStructuredDocument} for the JSP file being translated */
	IStructuredDocument fStructuredDocument = null;
	
	/** the EL translator */
	private IJSPELTranslator fELTranslator = null;
	
	/** reported translation problems */
	private List fTranslationProblems = new ArrayList();
	
	/** fSourcePosition = position in JSP source */
	private int fSourcePosition = -1;
	
	/** fRelativeOffest = offset in the buffer there the cursor is */
	private int fRelativeOffset = -1;
	
	/** fCursorPosition = offset in the translated java document */
	private int fCursorPosition = -1;

	/** some page directive attributes */
	private boolean fIsErrorPage = false;
	private boolean fCursorInExpression = false;
	private boolean fIsInASession = true;

	/** user java code in body of the service method */
	private StringBuffer fUserCode = new StringBuffer();
	/** user EL Expression */
	private StringBuffer fUserELExpressions = new StringBuffer();
	/** user defined vars declared in the beginning of the class */
	private StringBuffer fUserDeclarations = new StringBuffer();

	/**
	 * A map of tag names to tag library variable information; used to store
	 * the ones needed for AT_END variable support.
	 */
	private StackMap fTagToVariableMap = null;
	private Stack fUseBeansStack = new Stack();

	/** the final translated java document */
	private StringBuffer fResult;
	
	/** the buffer where the cursor is */
	private StringBuffer fCursorOwner = null;

	private IStructuredDocumentRegion fCurrentNode;
	
	/** flag for if the cursor is in the current regionb eing translated */
	private boolean fInCodeRegion = false;

	/** used to avoid infinite looping include files */
	private Stack fIncludes = null;
	private Set fIncludedPaths = new HashSet(2);
	private boolean fProcessIncludes = true;
	/** mostly for helper classes, so they parse correctly */
	private ArrayList fBlockMarkers = null;
	/**
	 * for keeping track of offset in user buffers while document is being
	 * built
	 */
	private int fOffsetInUserImports = 0;
	private int fOffsetInUserDeclarations = 0;
	private int fOffsetInUserCode = 0;

	/** correlates ranges (positions) in java to ranges in jsp */
	private HashMap fJava2JspRanges = new HashMap();

	/**
	 * map of ranges in fUserImports (relative to the start of the buffer) to
	 * ranges in source JSP buffer.
	 */
	private HashMap fImportRanges = new HashMap();
	/**
	 * map of ranges in fUserCode (relative to the start of the buffer) to
	 * ranges in source JSP buffer.
	 */
	private HashMap fCodeRanges = new HashMap();
	/**
	 * map of ranges in fUserDeclarations (relative to the start of the
	 * buffer) to ranges in source JSP buffer.
	 */
	private HashMap fDeclarationRanges = new HashMap();

	private HashMap fUseBeanRanges = new HashMap();

	private HashMap fUserELRanges = new HashMap();

	/**
	 * ranges that don't directly map from java code to JSP code (eg.
	 * <%@include file="included.jsp"%>
	 */
	private HashMap fIndirectRanges = new HashMap();

	private IProgressMonitor fProgressMonitor = null;

	/**
	 * save JSP document text for later use may just want to read this from
	 * the file or strucdtured document depending what is available
	 */
	private StringBuffer fJspTextBuffer = new StringBuffer();

	/** EL Translator ID (pluggable) */
	private String fELTranslatorID;

	/**
	 * <code>true</code> if code has been found, such as HTML tags, that is not translated
	 * <code>false</code> otherwise.  Useful for deciding if a place holder needs to be
	 * written to translation
	 */
	private boolean fFoundNonTranslatedCode;

	/**
	 * <code>true</code> if code has been translated for the current region,
	 * <code>false</code> otherwise
	 */
	private boolean fCodeTranslated;

	/**
	 * A structure for holding a region collection marker and list of variable
	 * information. The region can be used later for positioning validation
	 * messages.
	 */
	static class RegionTags {
		ITextRegionCollection region;
		CustomTag tag;

		RegionTags(ITextRegionCollection region, CustomTag tag) {
			this.region = region;
			this.tag = tag;
		}
	}

	public JSPTranslator() {
		init();
	}

	/**
	 * configure using an XMLNode
	 * 
	 * @param node
	 * @param monitor
	 */
	private void configure(IDOMNode node, IProgressMonitor monitor) {

		fProgressMonitor = monitor;
		fStructuredModel = node.getModel();
		String baseLocation = fStructuredModel.getBaseLocation();

		fELTranslatorID = getELTranslatorProperty(baseLocation);

		fStructuredDocument = fStructuredModel.getStructuredDocument();

		String className = createClassname(node);
		if (className.length() > 0) {
			setClassname(className);
			fClassHeader = "public class " + className + " extends "; //$NON-NLS-1$ //$NON-NLS-2$
		}

	}

	/**
	 * memory saving configure (no StructuredDocument in memory) currently
	 * doesn't handle included files
	 * 
	 * @param jspFile
	 * @param monitor
	 */
	private void configure(IFile jspFile, IProgressMonitor monitor) {
		// when configured on a file
		// fStructuredModel, fPositionNode, fModelQuery, fStructuredDocument
		// are all null
		fProgressMonitor = monitor;

		fELTranslatorID = getELTranslatorProperty(jspFile);

		String className = createClassname(jspFile);
		if (className.length() > 0) {
			setClassname(className);
			fClassHeader = "public class " + className + " extends "; //$NON-NLS-1$ //$NON-NLS-2$
		}
	}

	/**
	 * Set the jsp text from an IFile
	 * 
	 * @param jspFile
	 */
	private void setJspText(IFile jspFile) {
		try {
			BufferedInputStream in = new BufferedInputStream(jspFile.getContents());
			BufferedReader reader = new BufferedReader(new InputStreamReader(in));
			String line = null;
			while ((line = reader.readLine()) != null) {
				fJspTextBuffer.append(line);
				fJspTextBuffer.append(ENDL);
			}
			reader.close();
		}
		catch (CoreException e) {
			Logger.logException(e);
		}
		catch (IOException e) {
			Logger.logException(e);
		}
	}

	/**
	 * Get the value of the ELTranslator property from a workspace relative
	 * path string
	 * 
	 * @param baseLocation
	 *            Workspace-relative string path
	 * @return Value of the ELTranslator property associated with the project.
	 */
	private String getELTranslatorProperty(String baseLocation) {
		IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
		String elTranslatorValue = null;
		IFile file = workspaceRoot.getFile(new Path(baseLocation));
		if (file != null) {
			elTranslatorValue = getELTranslatorProperty(file);
		}
		return elTranslatorValue;
	}

	/**
	 * Get the value of the ELTranslator property from an IFile
	 * 
	 * @param file
	 *            IFile
	 * @return Value of the ELTranslator property associated with the project.
	 */
	private String getELTranslatorProperty(IFile file) {
		String elTranslatorValue = null;
		if (file != null) {
			if (file.exists()) {
				try {
					elTranslatorValue = file.getPersistentProperty(new QualifiedName(JSP_CORE_PLUGIN_ID, ELTRANSLATOR_PROP_NAME));
					if (null == elTranslatorValue) {

						elTranslatorValue = file.getProject().getPersistentProperty(new QualifiedName(JSP_CORE_PLUGIN_ID, ELTRANSLATOR_PROP_NAME));
					}
				}
				catch (CoreException e) {
					// ISSUE: why do we log this here? Instead of allowing to
					// throwup?
					Logger.logException(e);
				}

			}
		}
		return elTranslatorValue;
	}

	/**
	 * @param node
	 * @return the simple class name, not fully qualified
	 */
	private String createClassname(IDOMNode node) {
		String classname = ""; //$NON-NLS-1$
		if (node != null) {
			String base = node.getModel().getBaseLocation();
			classname = JSP2ServletNameUtil.mangle(base);
		}
		return classname;
	}

	/**
	 * @param jspFile
	 * @return
	 */
	private String createClassname(IFile jspFile) {

		String classname = ""; //$NON-NLS-1$
		if (jspFile != null) {
			classname = JSP2ServletNameUtil.mangle(jspFile.getFullPath().toString());
		}
		return classname;
	}

	private IJSPProblem createJSPProblem(final int problemEID, final int problemID, final String message, final int start, final int end) {
		final int line = fStructuredDocument.getLineOfOffset(start);
		final char[] classname = fClassname.toCharArray();

		/*
		 * Note: these problems would result in translation errors on the
		 * server, so the severity is not meant to be controllable
		 */
		return new IJSPProblem() {
			public void setSourceStart(int sourceStart) {
			}

			public void setSourceLineNumber(int lineNumber) {
			}

			public void setSourceEnd(int sourceEnd) {
			}

			public boolean isWarning() {
				return false;
			}

			public boolean isError() {
				return true;
			}

			public int getSourceStart() {
				return start;
			}

			public int getSourceLineNumber() {
				return line;
			}

			public int getSourceEnd() {
				return end;
			}

			public char[] getOriginatingFileName() {
				return classname;
			}

			public String getMessage() {
				return message;
			}

			public int getID() {
				return problemID;
			}

			public String[] getArguments() {
				return new String[0];
			}

			public int getEID() {
				return problemEID;
			}
		};
	}

	public void setClassname(String classname) {
		this.fClassname = classname;
	}

	public String getClassname() {
		return this.fClassname != null ? this.fClassname : "GenericJspServlet"; //$NON-NLS-1$
	}

	/**
	 * So that the JSPTranslator can be reused.
	 */
	public void reset(IDOMNode node, IProgressMonitor progress) {

		// initialize some things on node
		configure(node, progress);
		reset();
		// set the jsp text buffer
		fJspTextBuffer.append(fStructuredDocument.get());
	}

	/**
	 * conservative version (no StructuredDocument/Model)
	 * 
	 * @param jspFile
	 * @param progress
	 */
	public void reset(IFile jspFile, IProgressMonitor progress) {

		// initialize some things on node
		configure(jspFile, progress);
		reset();
		// set the jsp text buffer
		setJspText(jspFile);
	}

	/**
	 * Reinitialize some fields
	 */
	void reset() {

		// reset progress monitor
		if (fProgressMonitor != null)
			fProgressMonitor.setCanceled(false);

		// reinit fields
		fSourcePosition = -1;
		fRelativeOffset = -1;
		fCursorPosition = -1;

		fIsErrorPage = fCursorInExpression = false;
		fIsInASession = true;

		fUserCode = new StringBuffer();
		fUserDeclarations = new StringBuffer();
		fUserImports = new StringBuffer();
		fUserELExpressions = new StringBuffer();

		fResult = null;
		fCursorOwner = null; // the buffer where the cursor is

		fCurrentNode = null;
		fInCodeRegion = false; // flag for if cursor is in the current region
		// being translated

		if (fIncludes != null)
			fIncludes.clear();

		fBlockMarkers = null;

		fOffsetInUserImports = 0;
		fOffsetInUserDeclarations = 0;
		fOffsetInUserCode = 0;

		fJava2JspRanges.clear();
		fImportRanges.clear();
		fCodeRanges.clear();
		fUseBeanRanges.clear();
		fDeclarationRanges.clear();
		fUserELRanges.clear();
		fIndirectRanges.clear();
		fIncludedPaths.clear();

		fJspTextBuffer = new StringBuffer();
		
		fFoundNonTranslatedCode = false;
		fCodeTranslated = false;

	}

	/**
	 * @return just the "shell" of a servlet, nothing contributed from the JSP
	 *         doc
	 */
	public final StringBuffer getEmptyTranslation() {
		reset();
		buildResult(true);
		return getTranslation();
	}

	/**
	 * <p>put the final java document together</p>
	 * 
	 * @param updateRanges <code>true</code> if the ranges need to be updated as the result
	 * is built, <code>false</code> if the ranges have already been updated.  This is useful
	 * if building a result from a persisted {@link JSPTranslator}.
	 */
	private final void buildResult(boolean updateRanges) {
		// to build the java document this is the order:
		// 
		// + default imports
		// + user imports
		// + class header
		// [+ error page]
		// + user declarations
		// + service method header
		// + try/catch start
		// + user code
		// + try/catch end
		// + service method footer
		fResult = new StringBuffer(fImplicitImports.length() + fUserImports.length() + fClassHeader.length() +
				fUserDeclarations.length() + fServiceHeader.length() + TRY_CATCH_START.length()
				+ fUserCode.length() + TRY_CATCH_END.length() + FOOTER.length());

		int javaOffset = 0;

		fResult.append(fImplicitImports);
		javaOffset += fImplicitImports.length();

		// updateRanges(fIndirectImports, javaOffset);
		if(updateRanges) {
			updateRanges(fImportRanges, javaOffset);
		}
		// user imports
		append(fUserImports);
		javaOffset += fUserImports.length();

		// class header
		fResult.append(fClassHeader);
		javaOffset += fClassHeader.length();
		fResult.append(fSuperclass + "{" + ENDL); //$NON-NLS-1$
		javaOffset += fSuperclass.length() + 2;

		if(updateRanges) {
			updateRanges(fDeclarationRanges, javaOffset);
		}
		// user declarations
		append(fUserDeclarations);
		javaOffset += fUserDeclarations.length();

		if(updateRanges) {
			updateRanges(fUserELRanges, javaOffset);
		}
		append(fUserELExpressions);
		javaOffset += fUserELExpressions.length();

		fResult.append(fServiceHeader);
		javaOffset += fServiceHeader.length();
		// session participant
		if (fIsInASession) {
			fResult.append(SESSION_VARIABLE_DECLARATION);
			javaOffset += SESSION_VARIABLE_DECLARATION.length();
		}
		// error page
		if (fIsErrorPage) {
			fResult.append(EXCEPTION);
			javaOffset += EXCEPTION.length();
		}


		fResult.append(TRY_CATCH_START);
		javaOffset += TRY_CATCH_START.length();

		if(updateRanges) {
			updateRanges(fCodeRanges, javaOffset);
		}

		// user code
		append(fUserCode);
		javaOffset += fUserCode.length();


		fResult.append(TRY_CATCH_END);
		javaOffset += TRY_CATCH_END.length();

		// footer
		fResult.append(FOOTER);
		javaOffset += FOOTER.length();

		fJava2JspRanges.putAll(fImportRanges);
		fJava2JspRanges.putAll(fDeclarationRanges);
		fJava2JspRanges.putAll(fCodeRanges);
		fJava2JspRanges.putAll(fUserELRanges);

	}

	/**
	 * @param javaRanges
	 * @param offsetInJava
	 */
	private void updateRanges(HashMap rangeMap, int offsetInJava) {
		// just need to update java ranges w/ the offset we now know
		Iterator it = rangeMap.keySet().iterator();
		while (it.hasNext())
			((Position) it.next()).offset += offsetInJava;
	}

	/**
	 * map of ranges (positions) in java document to ranges in jsp document
	 * 
	 * @return a map of java positions to jsp positions.
	 */
	public HashMap getJava2JspRanges() {
		return fJava2JspRanges;
	}

	/**
	 * map of ranges in jsp document to ranges in java document.
	 * 
	 * @return a map of jsp positions to java positions, or null if no
	 *         translation has occured yet (the map hasn't been built).
	 */
	public HashMap getJsp2JavaRanges() {
		if (fJava2JspRanges == null)
			return null;
		HashMap flipFlopped = new HashMap();
		Iterator keys = fJava2JspRanges.keySet().iterator();
		Object range = null;
		while (keys.hasNext()) {
			range = keys.next();
			flipFlopped.put(fJava2JspRanges.get(range), range);
		}
		return flipFlopped;
	}

	public HashMap getJava2JspImportRanges() {
		return fImportRanges;
	}

	public HashMap getJava2JspUseBeanRanges() {
		return fUseBeanRanges;
	}

	public HashMap getJava2JspIndirectRanges() {
		return fIndirectRanges;
	}

	/**
	 * Adds to the jsp<->java map by default
	 * 
	 * @param value
	 *            a comma delimited list of imports
	 */
	protected void addImports(String value) {
		addImports(value, true);
	}

	/**
	 * Pass in a comma delimited list of import values, appends each to the
	 * final result buffer
	 * 
	 * @param value
	 *            a comma delimited list of imports
	 */
	protected void addImports(String value, boolean addToMap) {
		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=81687
		// added the "addToMap" parameter to exclude imports originating
		// from included JSP files to be added to the jsp<->java mapping
		StringTokenizer st = new StringTokenizer(value, ",", false); //$NON-NLS-1$
		String tok = ""; //$NON-NLS-1$
		// String appendage = ""; //$NON-NLS-1$
		while (st.hasMoreTokens()) {
			tok = st.nextToken();
			appendImportToBuffer(tok, fCurrentNode, addToMap);
		}
	}

	/**
	 * /* keep track of cursor position inside the buffer /* appends buffer to
	 * the final result buffer
	 */
	protected void append(StringBuffer buf) {
		if (getCursorOwner() == buf) {
			fCursorPosition = fResult.length() + getRelativeOffset();
		}
		fResult.append(buf.toString());
	}

	/**
	 * Only valid after a configure(...), translate(...) or
	 * translateFromFile(...) call
	 * 
	 * @return the current result (java translation) buffer
	 */
	public final StringBuffer getTranslation() {

		if (DEBUG) {
			StringBuffer debugString = new StringBuffer();
			try {
				Iterator it = fJava2JspRanges.keySet().iterator();
				while (it.hasNext()) {
					debugString.append("--------------------------------------------------------------\n"); //$NON-NLS-1$
					Position java = (Position) it.next();
					debugString.append("Java range:[" + java.offset + ":" + java.length + "]\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
					debugString.append("[" + fResult.toString().substring(java.offset, java.offset + java.length) + "]\n"); //$NON-NLS-1$ //$NON-NLS-2$
					debugString.append("--------------------------------------------------------------\n"); //$NON-NLS-1$
					debugString.append("|maps to...|\n"); //$NON-NLS-1$
					debugString.append("==============================================================\n"); //$NON-NLS-1$
					Position jsp = (Position) fJava2JspRanges.get(java);
					debugString.append("JSP range:[" + jsp.offset + ":" + jsp.length + "]\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
					debugString.append("[" + fJspTextBuffer.toString().substring(jsp.offset, jsp.offset + jsp.length) + "]\n"); //$NON-NLS-1$ //$NON-NLS-2$
					debugString.append("==============================================================\n"); //$NON-NLS-1$
					debugString.append("\n"); //$NON-NLS-1$
					debugString.append("\n"); //$NON-NLS-1$
				}
			}
			catch (Exception e) {
				Logger.logException("JSPTranslation error", e); //$NON-NLS-1$
			}
			Logger.log(Logger.INFO_DEBUG, debugString.toString());
		}

		return fResult;
	}

	public List getTranslationProblems() {
		return fTranslationProblems;
	}

	/**
	 * Only valid after a configure(...), translate(...) or
	 * translateFromFile(...) call
	 * 
	 * @return the text in the JSP file
	 */
	public final String getJspText() {
		return fJspTextBuffer.toString();
	}

	
	protected void addTaglibVariables(String tagToAdd, ITextRegionCollection customTag) {
		addTaglibVariables(tagToAdd, customTag, -1);
	}
	/**
	 * Add the server-side scripting variables used by this tag, along with
	 * any scoping.
	 * 
	 * @param tagToAdd
	 * @param customTag
	 */
	protected void addTaglibVariables(String tagToAdd, ITextRegionCollection customTag, int index) {
		if (customTag.getFirstRegion().getType().equals(DOMRegionContext.XML_TAG_OPEN)) {
			/*
			 * Start tag
			 */
			addStartTagVariable(tagToAdd, customTag,index);
		}
		else if (customTag.getFirstRegion().getType().equals(DOMRegionContext.XML_END_TAG_OPEN)) {
			/*
			 * End tag
			 */
			addEndTagVariable(tagToAdd, customTag);
		}
	}
	
	private void addEndTagVariable(String tagToAdd, ITextRegionCollection customTag){
		IFile f = getFile();
		if (f == null || !f.exists())
			return;
		String decl = ""; //$NON-NLS-1$
		RegionTags regionTag = (RegionTags) fTagToVariableMap.pop(tagToAdd);
		if (regionTag != null) {
			// even an empty array will indicate a need for a closing brace
			TaglibVariable[] taglibVars = regionTag.tag.getTagVariables();
			StringBuffer text = new StringBuffer();
			if (regionTag.tag.isIterationTag())
				doAfterBody(text, regionTag);
			text.append("} // </"); //$NON-NLS-1$
			text.append(tagToAdd);
			text.append(">\n"); //$NON-NLS-1$
			appendToBuffer(text.toString(), fUserCode, false, customTag);
			for (int i = 0; i < taglibVars.length; i++) {
				if (taglibVars[i].getScope() == VariableInfo.AT_END) {
					decl = taglibVars[i].getDeclarationString();
					appendToBuffer(decl, fUserCode, false, customTag);
				}
			}
		}
		else {
			/*
			 * Since something should have been in the map because of a
			 * start tag, its absence now means an unbalanced end tag.
			 * Extras will be checked later to flag unbalanced start tags.
			 */
			IJSPProblem missingStartTag = createJSPProblem(IJSPProblem.StartCustomTagMissing, IJSPProblem.F_PROBLEM_ID_LITERAL, NLS.bind(JSPCoreMessages.JSPTranslator_4, tagToAdd), customTag.getStartOffset(), customTag.getEndOffset());
			fTranslationProblems.add(missingStartTag);
		}
	}
	private void addStartTagVariable(String tagToAdd,ITextRegionCollection customTag, int index){
		IFile f = getFile();

		if (f == null || !f.exists())
			return;
		TaglibHelper helper = TaglibHelperManager.getInstance().getTaglibHelper(f);
		String decl = ""; //$NON-NLS-1$
		List problems = new ArrayList();
		CustomTag tag = helper.getCustomTag(tagToAdd, getStructuredDocument(), customTag, problems);
		TaglibVariable[] taglibVars = tag.getTagVariables();
		fTranslationProblems.addAll(problems);
		/*
		 * Add AT_BEGIN variables
		 */
		for (int i = 0; i < taglibVars.length; i++) {
			if (taglibVars[i].getScope() == VariableInfo.AT_BEGIN) {
				decl = taglibVars[i].getDeclarationString();
				appendToBuffer(decl, fUserCode, false, customTag);
			}
		}
		boolean isEmptyTag = false;
		if (index != -1)
			isEmptyTag= isEmptyTag(customTag, index);
		else
			isEmptyTag= isEmptyTag(customTag);
		
		/*
		 * Add a single  { to limit the scope of NESTED variables
		 */
		StringBuffer text = new StringBuffer();
		if (!isEmptyTag && tag.isIterationTag() && tag.getTagClassName() != null) {
			text.append("\nwhile(true) "); //$NON-NLS-1$
		}
		text.append("{ // <"); //$NON-NLS-1$
		text.append(tagToAdd);
		if (isEmptyTag)
			text.append("/>\n"); //$NON-NLS-1$
		else
			text.append(">\n"); //$NON-NLS-1$

		appendToBuffer(text.toString(), fUserCode, false, customTag);

		for (int i = 0; i < taglibVars.length; i++) {
			if (taglibVars[i].getScope() == VariableInfo.NESTED) {
				decl = taglibVars[i].getDeclarationString();
				appendToBuffer(decl, fUserCode, false, customTag);
			}
		}
		/*
		 * For empty tags, add the corresponding } and AT_END variables immediately.  
		 */
		if (isEmptyTag) {
			text = new StringBuffer();
			text.append("} // <"); //$NON-NLS-1$
			text.append(tagToAdd);
			text.append("/>\n"); //$NON-NLS-1$
			appendToBuffer(text.toString(), fUserCode, false, customTag);
			/* Treat this as the end for empty tags */
			for (int i = 0; i < taglibVars.length; i++) {
				if (taglibVars[i].getScope() == VariableInfo.AT_END) {
					decl = taglibVars[i].getDeclarationString();
					appendToBuffer(decl, fUserCode, false, customTag);
				}
			}
		}
		else {
			/*
			 * For non-empty tags, remember the variable information
			 */
			fTagToVariableMap.push(tagToAdd, new RegionTags(customTag, tag));
		}
		
	}

	private boolean isEmptyTag(ITextRegionCollection customTag, int index) {
		String type = null;
		// custom tag is embedded
		ITextRegionList regions = customTag.getRegions();
		ITextRegion nextRegion = regions.get(index);
		int size = customTag.getNumberOfRegions() ;
		type = nextRegion.getType();
		while (index <= size && !(DOMRegionContext.XML_EMPTY_TAG_CLOSE.equals(type) || DOMRegionContext.XML_TAG_NAME.equals(type) || DOMRegionContext.XML_TAG_CLOSE.equals(type) )) {
				nextRegion = regions.get(++index);
				type = nextRegion.getType();
		}
		
		return DOMRegionContext.XML_EMPTY_TAG_CLOSE.equals(type);
	}
	
	private boolean isEmptyTag(ITextRegionCollection customTag) {
		ITextRegion lastRegion = customTag.getLastRegion();
		// custom tag is embedded
		if (customTag instanceof ITextRegionContainer) {
			ITextRegionList regions = customTag.getRegions();
			int size = customTag.getNumberOfRegions() - 1;
			while (size > 0 && !(DOMRegionContext.XML_EMPTY_TAG_CLOSE.equals(lastRegion.getType()) || DOMRegionContext.XML_TAG_NAME.equals(lastRegion.getType()) || DOMRegionContext.XML_TAG_CLOSE.equals(lastRegion.getType()) )) {
				lastRegion = regions.get(--size);
			}
		}
		
		return DOMRegionContext.XML_EMPTY_TAG_CLOSE.equals(lastRegion.getType());
	}

	private void addCustomTaglibVariables(String tagToAdd, ITextRegionCollection customTag, ITextRegion prevRegion, int index) {
		//Can't judge by first region as start and end tag are part of same ContextRegionContainer		
		if (prevRegion != null && prevRegion.getType().equals(DOMRegionContext.XML_END_TAG_OPEN)) {
			/*
			 * End tag
			 */
			addEndTagVariable(tagToAdd, customTag);
		}
		else if (prevRegion != null && prevRegion.getType().equals(DOMRegionContext.XML_TAG_OPEN)) {
			/*
			 * Start tag
			 */
			addStartTagVariable(tagToAdd,customTag, index);
		}
	}

	private void doAfterBody(StringBuffer buffer, RegionTags regionTag) {
		buffer.append("\tif ( (new "); //$NON-NLS-1$
		buffer.append(regionTag.tag.getTagClassName());
		buffer.append("()).doAfterBody() != javax.servlet.jsp.tagext.BodyTag.EVAL_BODY_AGAIN)\n\t\tbreak;\n"); //$NON-NLS-1$
	}

	/**
	 * @return the workspace file for this model, null otherwise
	 */
	private IFile getFile() {
		IFile f = null;
		ITextFileBuffer buffer = FileBufferModelManager.getInstance().getBuffer(getStructuredDocument());
		if (buffer != null) {
			IPath path = buffer.getLocation();
			if (path.segmentCount() > 1) {
				f = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
			}
			if (f != null && f.isAccessible()) {
				return f;
			}
		}
		return null;
	}

	/*
	 * used by inner helper class (XMLJSPRegionHelper, JSPIncludeRegionHelper)
	 */
	public List getBlockMarkers() {
		if (fBlockMarkers == null)
			fBlockMarkers = new ArrayList();
		return fBlockMarkers;
	}

	/**
	 * the main control loop for translating the document, driven by the
	 * structuredDocument nodes
	 */
	public void translate() {
		if (fTagToVariableMap == null) {
			fTagToVariableMap = new StackMap();
		}
		fTranslationProblems.clear();

		setCurrentNode(new ZeroStructuredDocumentRegion(fStructuredDocument, 0));
		translatePreludes();

		setCurrentNode(fStructuredDocument.getFirstStructuredDocumentRegion());

		while (getCurrentNode() != null && !isCanceled()) {
			//no code has been translated for this region yet
			fCodeTranslated = false;
			// intercept HTML comment flat node
			// also handles UNDEFINED (which is what CDATA comes in as)
			// basically this part will handle any "embedded" JSP containers
			if (getCurrentNode().getType() == DOMRegionContext.XML_COMMENT_TEXT || getCurrentNode().getType() == DOMRegionContext.XML_CDATA_TEXT || getCurrentNode().getType() == DOMRegionContext.UNDEFINED) {
				translateXMLCommentNode(getCurrentNode());
			}
			else {
				// iterate through each region in the flat node
				translateRegionContainer(getCurrentNode(), STANDARD_JSP);
			}
			
			//if no code was translated for this region then found "non translated code"
			if(!fCodeTranslated) {
				fFoundNonTranslatedCode = true;
			}
			
			if (getCurrentNode() != null)
				advanceNextNode();
		}
		
		writePlaceHolderForNonTranslatedCode();

		setCurrentNode(new ZeroStructuredDocumentRegion(fStructuredDocument, fStructuredDocument.getLength()));
		translateCodas();

		/*
		 * Any contents left in the map indicate start tags that never had end
		 * tags. While the '{' that is present without the matching '}' should
		 * cause a Java translation fault, that's not particularly helpful to
		 * a user who may only know how to use custom tags as tags. Ultimately
		 * unbalanced custom tags should just be reported as unbalanced tags,
		 * and unbalanced '{'/'}' only reported when the user actually
		 * unbalanced them with scriptlets.
		 */
		Iterator regionAndTaglibVariables = fTagToVariableMap.values().iterator();
		while (regionAndTaglibVariables.hasNext()) {
			RegionTags regionTag = (RegionTags) regionAndTaglibVariables.next();
			ITextRegionCollection extraStartRegion = regionTag.region;
			IJSPProblem missingEndTag = createJSPProblem(IJSPProblem.EndCustomTagMissing, IJSPProblem.F_PROBLEM_ID_LITERAL, NLS.bind(JSPCoreMessages.JSPTranslator_5,regionTag.tag.getTagName()), extraStartRegion.getStartOffset(), extraStartRegion.getEndOffset());
			fTranslationProblems.add(missingEndTag);

			StringBuffer text = new StringBuffer();
			// Account for iteration tags that have a missing end tag
			if (regionTag.tag.isIterationTag())
				doAfterBody(text, regionTag);
			text.append("} // [</"); //$NON-NLS-1$
			text.append(regionTag.tag.getTagName());
			text.append(">]"); //$NON-NLS-1$
			appendToBuffer(text.toString(), fUserCode, false, fStructuredDocument.getLastStructuredDocumentRegion());
		}
		fTagToVariableMap.clear();

		/*
		 * Now do the same for jsp:useBean tags, whose contents get their own
		 * { & }
		 */
		while (!fUseBeansStack.isEmpty()) {
			appendToBuffer("}", fUserCode, false, fStructuredDocument.getLastStructuredDocumentRegion()); //$NON-NLS-1$
			ITextRegionCollection extraStartRegion = (ITextRegionCollection) fUseBeansStack.pop();
			IJSPProblem missingEndTag = createJSPProblem(IJSPProblem.UseBeanEndTagMissing, IJSPProblem.F_PROBLEM_ID_LITERAL, NLS.bind(JSPCoreMessages.JSPTranslator_5,JSP11Namespace.ElementName.USEBEAN), extraStartRegion.getStartOffset(), extraStartRegion.getEndOffset());
			fTranslationProblems.add(missingEndTag);
		}

		buildResult(true);
	}

 	/**
	 * Translates a region container (and XML JSP container, or <% JSP
	 * container). This method should only be called in this class and for
	 * containers in the primary structured document as all buffer appends
	 * will be direct.
	 */
	protected void setDocumentContent(IDocument document, InputStream contentStream, String charset) {
		Reader in = null;
		try {
			in = new BufferedReader(new InputStreamReader(contentStream, charset), 2048);
			StringBuffer buffer = new StringBuffer(2048);
			char[] readBuffer = new char[2048];
			int n = in.read(readBuffer);
			while (n > 0) {
				buffer.append(readBuffer, 0, n);
				n = in.read(readBuffer);
			}
			document.set(buffer.toString());
		}
		catch (IOException x) {
			// ignore
		}
		finally {
			if (in != null) {
				try {
					in.close();
				}
				catch (IOException x) {
					// ignore
				}
			}
		}
	}

	protected void init() {
		fClassname = "_JSPServlet"; //$NON-NLS-1$
		fClassHeader = "public class " + fClassname + " extends "; //$NON-NLS-1$ //$NON-NLS-2$
		
		fImplicitImports = "import javax.servlet.*;" + ENDL + //$NON-NLS-1$
					"import javax.servlet.http.*;" + ENDL + //$NON-NLS-1$
					"import javax.servlet.jsp.*;" + ENDL + ENDL; //$NON-NLS-1$

		fServiceHeader = "public void _jspService(javax.servlet.http.HttpServletRequest request," + //$NON-NLS-1$
					" javax.servlet.http.HttpServletResponse response)" + ENDL + //$NON-NLS-1$
					"\t\tthrows java.io.IOException, javax.servlet.ServletException {" + ENDL + //$NON-NLS-1$
					"javax.servlet.jsp.PageContext pageContext = JspFactory.getDefaultFactory().getPageContext(this, request, response, null, true, JspWriter.DEFAULT_BUFFER, true);" + ENDL + //$NON-NLS-1$
					"javax.servlet.ServletContext application = pageContext.getServletContext();" + ENDL + //$NON-NLS-1$
					"javax.servlet.ServletConfig config = pageContext.getServletConfig();" + ENDL + //$NON-NLS-1$ 
					"javax.servlet.jsp.JspWriter out = pageContext.getOut();" + ENDL + //$NON-NLS-1$
					"Object page = this;" + ENDL; //$NON-NLS-1$
		fSuperclass = "javax.servlet.http.HttpServlet"; //$NON-NLS-1$
	}

	/**
	 * 
	 * @return the status of the translator's progrss monitor, false if the
	 *         monitor is null
	 */
	private boolean isCanceled() {
		return (fProgressMonitor == null) ? false : fProgressMonitor.isCanceled();
	}

	private void advanceNextNode() {
		setCurrentNode(getCurrentNode().getNext());
		if (getCurrentNode() != null)
			setSourceReferencePoint();
	}

	private void setSourceReferencePoint() {
		if (isJSP(getCurrentNode().getFirstRegion().getType())) {
			Iterator it = getCurrentNode().getRegions().iterator();
			ITextRegion r = null;
			while (it.hasNext()) {
				r = (ITextRegion) it.next();
				if (r.getType() == DOMJSPRegionContexts.JSP_CONTENT || r.getType() == DOMRegionContext.XML_CONTENT)
					break;
				else if (r.getType() == DOMJSPRegionContexts.JSP_DIRECTIVE_NAME)
					break;
				else if (r.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE && getCurrentNode().getFullText(r).trim().equals("import")) //$NON-NLS-1$
					break;
			}
		}
	}

	/**
	 * translates a region container (and XML JSP container, or <% JSP
	 * container)
	 * 
	 * This method should only be called in this class and for containers in
	 * the primary structured document as all buffer appends will be direct
	 */
	protected void translateRegionContainer(ITextRegionCollection container, int JSPType) {

		ITextRegionCollection containerRegion = container;

		Iterator regions = containerRegion.getRegions().iterator();
		ITextRegion region = null;
		while (regions.hasNext()) {
			region = (ITextRegion) regions.next();
			String type = region.getType();

			// content assist was not showing up in JSP inside a javascript region
			if (DOMRegionContext.BLOCK_TEXT == type) {
				// check if it's nested jsp in a script tag...
				if (region instanceof ITextRegionContainer) {
					// pass in block text's container & iterator
					Iterator regionIterator = ((ITextRegionCollection) region).getRegions().iterator();
					translateJSPNode(region, regionIterator, type, EMBEDDED_JSP);
				}
				else {
					//be sure to combine all of the text from the block region
					StringBuffer fullText = new StringBuffer(containerRegion.getFullText(region));
					while(regions.hasNext()) {
						region = (ITextRegion)regions.next();
						if (region instanceof ITextRegionContainer) {
							// pass in block text's container & iterator
							Iterator regionIterator = ((ITextRegionCollection) region).getRegions().iterator();
							translateJSPNode(region, regionIterator, type, EMBEDDED_JSP);
						}
						
						if(region.getType() == DOMRegionContext.BLOCK_TEXT) {
							fullText.append(containerRegion.getFullText(region));
						} else {
							//update type for when we exit if statement for BLOCK_TEXT
							type = region.getType();
							break;
						}
					}
					
					/**
					 * LIMITATION - Normally the script content within a
					 * script tag is a single document region with a single
					 * BLOCK_TEXT text region within it. Any JSP scripting
					 * will be within its own region container (for the sake
					 * of keeping the scripting open/content/end as a group)
					 * also of BLOCK_TEXT. That ignores custom tags that might
					 * be in there, though, as they require proper scoping and
					 * variable declaration to be performed even though
					 * they're not proper nodes in the DOM. The only way to
					 * really do this is to treat the entire script content as
					 * JSP content on its own, akin to an included segment.
					 * Further complicating this solution is that tagdependent
					 * custom tags have their comment marked as BLOCK_TEXT as
					 * well, so there's no clear way to tell the two cases
					 * apart.
					 */

					// ////////////////////////////////////////////////////////////////////////////////
					// THIS EMBEDDED JSP TEXT WILL COME OUT LATER WHEN
					// PARTITIONING HAS
					// SUPPORT FOR NESTED XML-JSP
					// CMVC 241882
					decodeScriptBlock(fullText.toString(), containerRegion.getStartOffset());
					// ////////////////////////////////////////////////////////////////////////////////
				}
			}
			// if (region instanceof ITextRegionCollection &&
			// ((ITextRegionCollection) region).getNumberOfRegions() > 0) {
			// translateRegionContainer((ITextRegionCollection) region,
			// EMBEDDED_JSP);
			// }
			if (type != null && isJSP(type)) // <%, <%=, <%!, <%@
			{
				// translateJSPNode(region, regions, type, JSPType);
				translateJSPNode(containerRegion, regions, type, JSPType);
			}
			else if (type != null && (type == DOMRegionContext.XML_TAG_OPEN || type == DOMRegionContext.XML_END_TAG_OPEN)) {
				translateXMLNode(containerRegion, regions);
			}
			else if(type != null && type == DOMRegionContext.XML_CONTENT && region instanceof ITextRegionContainer) {
				//this case was put in to parse EL that is not in an attribute
				translateXMLContent((ITextRegionContainer)region);
			}
			//the end tags of these regions are "translated" in a sense
			else if(type == DOMJSPRegionContexts.JSP_DIRECTIVE_CLOSE ||
					type == DOMJSPRegionContexts.JSP_CLOSE) {
				this.fCodeTranslated = true;
			}
		}
	}

	/*
	 * ////////////////////////////////////////////////////////////////////////////////// **
	 * TEMP WORKAROUND FOR CMVC 241882 Takes a String and blocks out
	 * jsp:scriptlet, jsp:expression, and jsp:declaration @param blockText
	 * @return
	 */
	void decodeScriptBlock(String blockText, int startOfBlock) {
		XMLJSPRegionHelper helper = new XMLJSPRegionHelper(this, false);
		helper.addBlockMarker(new BlockMarker("jsp:scriptlet", null, DOMJSPRegionContexts.JSP_CONTENT, false)); //$NON-NLS-1$
		helper.addBlockMarker(new BlockMarker("jsp:expression", null, DOMJSPRegionContexts.JSP_CONTENT, false)); //$NON-NLS-1$
		helper.addBlockMarker(new BlockMarker("jsp:declaration", null, DOMJSPRegionContexts.JSP_CONTENT, false)); //$NON-NLS-1$
		helper.addBlockMarker(new BlockMarker("jsp:directive.include", null, DOMJSPRegionContexts.JSP_CONTENT, false)); //$NON-NLS-1$
		helper.addBlockMarker(new BlockMarker("jsp:directive.taglib", null, DOMJSPRegionContexts.JSP_CONTENT, false)); //$NON-NLS-1$
		helper.reset(blockText, startOfBlock);
		// force parse
		helper.forceParse();
	}

	/*
	 * returns string minus CDATA open and close text
	 */
	final public String stripCDATA(String text) {
		String resultText = ""; //$NON-NLS-1$
		String CDATA_OPEN = "<![CDATA["; //$NON-NLS-1$
		String CDATA_CLOSE = "]]>"; //$NON-NLS-1$
		int start = 0;
		int end = text.length();
		while (start < text.length()) {
			if (text.indexOf(CDATA_OPEN, start) > -1) {
				end = text.indexOf(CDATA_OPEN, start);
				resultText += text.substring(start, end);
				start = end + CDATA_OPEN.length();
			}
			else if (text.indexOf(CDATA_CLOSE, start) > -1) {
				end = text.indexOf(CDATA_CLOSE, start);
				resultText += text.substring(start, end);
				start = end + CDATA_CLOSE.length();
			}
			else {
				end = text.length();
				resultText += text.substring(start, end);
				break;
			}
		}
		return resultText;
	}

	// END OF WORKAROUND CODE...
	// /////////////////////////////////////////////////////////////////////////////////////
	/**
	 * determines if the type is a pure JSP type (not XML)
	 */
	protected boolean isJSP(String type) {
		return ((type == DOMJSPRegionContexts.JSP_DIRECTIVE_OPEN || type == DOMJSPRegionContexts.JSP_EXPRESSION_OPEN || type == DOMJSPRegionContexts.JSP_DECLARATION_OPEN || type == DOMJSPRegionContexts.JSP_SCRIPTLET_OPEN || type == DOMJSPRegionContexts.JSP_CONTENT || type == DOMJSPRegionContexts.JSP_EL_OPEN) && type != DOMRegionContext.XML_TAG_OPEN);
		// checking XML_TAG_OPEN so <jsp:directive.xxx/> gets treated like
		// other XML jsp tags
	}

	/**
	 * This currently only detects EL content and translates it,
	 * but if other cases arise later then they could be added in here
	 * 
	 * @param embeddedContainer the container that may contain EL
	 */
	protected void translateXMLContent(ITextRegionContainer embeddedContainer) {
		ITextRegionList embeddedRegions = embeddedContainer.getRegions();
		int length = embeddedRegions.size();
		for (int i = 0; i < length; i++) {
			ITextRegion delim = embeddedRegions.get(i);
			String type = delim.getType();

			// check next region to see if it's EL content
			if (i + 1 < length) {
				if((type == DOMJSPRegionContexts.JSP_EL_OPEN || type == DOMJSPRegionContexts.JSP_VBL_OPEN)) {
					ITextRegion region = null;
					
					int start = delim.getEnd();
					while (++i < length) {
						region = embeddedRegions.get(i);
						if (region == null || !isELType(region.getType()))
							break;
					}
					fLastJSPType = EXPRESSION;
					String elText = embeddedContainer.getFullText().substring(start, (region != null ? region.getStart() : embeddedContainer.getLength() - 1));
					translateEL(elText, embeddedContainer.getText(delim), fCurrentNode,
							embeddedContainer.getEndOffset(delim), elText.length());
				}
			}
		}
	}

	private boolean isELType(String type) {
		return DOMJSPRegionContexts.JSP_EL_CONTENT.equals(type) || DOMJSPRegionContexts.JSP_EL_DQUOTE.equals(type) || DOMJSPRegionContexts.JSP_EL_QUOTED_CONTENT.equals(type) || DOMJSPRegionContexts.JSP_EL_SQUOTE.equals(type);
	}

	/**
	 * translates the various XMLJSP type nodes
	 * 
	 * @param regions
	 *            the regions of the XMLNode
	 */
	protected void translateXMLNode(ITextRegionCollection container, Iterator regions) {
		// contents must be valid XHTML, translate escaped CDATA into what it
		// really is...
		ITextRegion r = null;
		if (regions.hasNext()) {
			r = (ITextRegion) regions.next();
			// <jsp:directive.xxx > comes in as this
			if (r.getType() == DOMRegionContext.XML_TAG_NAME || r.getType() == DOMJSPRegionContexts.JSP_DIRECTIVE_NAME)

			{
				String fullTagName = container.getText(r);
				if (fullTagName.indexOf(':') > -1 && !fullTagName.startsWith(JSP_PREFIX)) {
					addTaglibVariables(fullTagName, container,-1); // it
					// may
					// be a
					// custom
					// tag
				}
				StringTokenizer st = new StringTokenizer(fullTagName, ":.", false); //$NON-NLS-1$
				if (st.hasMoreTokens() && st.nextToken().equals("jsp")) //$NON-NLS-1$
				{
					if (st.hasMoreTokens()) {
						String jspTagName = st.nextToken();

						if (jspTagName.equals("scriptlet")) //$NON-NLS-1$
						{
							translateXMLJSPContent(SCRIPTLET);
						}
						else if (jspTagName.equals("expression")) //$NON-NLS-1$
						{
							translateXMLJSPContent(EXPRESSION);
						}
						else if (jspTagName.equals("declaration")) //$NON-NLS-1$
						{
							translateXMLJSPContent(DECLARATION);
						}
						else if (jspTagName.equals("directive")) //$NON-NLS-1$
						{
							if (st.hasMoreTokens()) {
								String directiveName = st.nextToken();
								if (directiveName.equals("taglib")) { //$NON-NLS-1$
									while (r != null && regions.hasNext() && !r.getType().equals(DOMRegionContext.XML_TAG_ATTRIBUTE_NAME)) {
										r = (ITextRegion) regions.next();
										if (container.getText(r).equals(JSP11Namespace.ATTR_NAME_PREFIX)) {
											String prefix = getAttributeValue(r, regions);
											if (prefix != null) {
												handleTaglib(prefix);
											}
										}
									}
									return;
								}
								else if (directiveName.equals("include")) { //$NON-NLS-1$

									String fileLocation = ""; //$NON-NLS-1$

									// skip to required "file" attribute,
									// should be safe because
									// "file" is the only attribute for the
									// include directive
									while (r != null && regions.hasNext() && !r.getType().equals(DOMRegionContext.XML_TAG_ATTRIBUTE_NAME)) {
										r = (ITextRegion) regions.next();
									}
									fileLocation = getAttributeValue(r, regions);
									if (fileLocation != null)
										handleIncludeFile(fileLocation);
								}
								else if (directiveName.equals("page")) { //$NON-NLS-1$

									// bad if currentNode is referenced after
									// here w/ the current list
									// see:
									// https://w3.opensource.ibm.com/bugzilla/show_bug.cgi?id=3035
									// setCurrentNode(getCurrentNode().getNext());
									if (getCurrentNode() != null) {
										// 'regions' contain the attrs
										translatePageDirectiveAttributes(regions, getCurrentNode());
									}
								}
								else if (directiveName.equals("tag")) { //$NON-NLS-1$
									translatePageDirectiveAttributes(regions, getCurrentNode());
								}
								else if (directiveName.equals("variable")) { //$NON-NLS-1$
									translateVariableDirectiveAttributes(regions);
								}
							}
						}
						else if (jspTagName.equals("include")) { //$NON-NLS-1$
							// <jsp:include page="filename") />
							checkAttributeValueContainer(regions, "page"); //$NON-NLS-1$
						}
						else if (jspTagName.equals("forward")) { //$NON-NLS-1$
							checkAttributeValueContainer(regions, "page"); //$NON-NLS-1$
						}
						else if (jspTagName.equals("param")) { //$NON-NLS-1$
							checkAttributeValueContainer(regions, "value"); //$NON-NLS-1$
						}
						else if (jspTagName.equals("setProperty")) { //$NON-NLS-1$
							checkAttributeValueContainer(regions, "value"); //$NON-NLS-1$
						}
						else if (jspTagName.equals("useBean")) //$NON-NLS-1$
						{
							checkAttributeValueContainer(regions, "name"); //$NON-NLS-1$
							// https://bugs.eclipse.org/bugs/show_bug.cgi?id=103004
							// advanceNextNode(); // get the content
							if (getCurrentNode() != null) {
								translateUseBean(container); // 'regions'
							}
						}

					}
				}
				else {
					checkAllAttributeValueContainers(regions);
				}
			}
		}
	}

	/**
	 * translates embedded containers for ALL attribute values
	 * 
	 * @param regions
	 */
	private void checkAllAttributeValueContainers(Iterator regions) {
		// tag name is not jsp
		// handle embedded jsp attributes...
		ITextRegion embedded = null;
		// Iterator attrRegions = null;
		// ITextRegion attrChunk = null;
		while (regions.hasNext()) {
			embedded = (ITextRegion) regions.next();
			if (embedded instanceof ITextRegionContainer) {
				// parse out container

				// https://bugs.eclipse.org/bugs/show_bug.cgi?id=130606
				// fix exponential iteration problem w/ embedded expressions
				translateEmbeddedJSPInAttribute((ITextRegionContainer) embedded);
				// attrRegions = ((ITextRegionContainer)
				// embedded).getRegions().iterator();
				// while (attrRegions.hasNext()) {
				// attrChunk = (ITextRegion) attrRegions.next();
				// String type = attrChunk.getType();
				// // embedded JSP in attribute support only want to
				// // translate one time per
				// // embedded region so we only translate on the JSP open
				// // tags (not content)
				// if (type == DOMJSPRegionContexts.JSP_EXPRESSION_OPEN ||
				// type ==
				// DOMJSPRegionContexts.JSP_SCRIPTLET_OPEN || type ==
				// DOMJSPRegionContexts.JSP_DECLARATION_OPEN || type ==
				// DOMJSPRegionContexts.JSP_DIRECTIVE_OPEN || type ==
				// DOMJSPRegionContexts.JSP_EL_OPEN) {
				// // now call jsptranslate
				// translateEmbeddedJSPInAttribute((ITextRegionContainer)
				// embedded);
				// break;
				// }
				// }
			}
		}
	}

	/**
	 * translates embedded container for specified attribute
	 * 
	 * @param regions
	 * @param attrName
	 */
	private void checkAttributeValueContainer(Iterator regions, String attrName) {
		ITextRegion r = null;
		while (regions.hasNext()) {
			r = (ITextRegion) regions.next();
			if (r.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME && getCurrentNode().getText(r).equals(attrName)) {
				// skip to attribute value
				while (regions.hasNext() && (r = (ITextRegion) regions.next()) != null) {
					if (r.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE)
						break;
				}
				// forces embedded region to be translated
				if (r instanceof ContextRegionContainer) {
					translateEmbeddedJSPInAttribute((ContextRegionContainer) r);
				}
				break;
			}
		}
	}

	/*
	 * example:
	 * 
	 * <jsp:scriptlet>scriptlet jsp-java content <![CDATA[ more jsp java ]]>
	 * jsp-java content... <![CDATA[ more jsp java ]]> </jsp:scriptlet>
	 * 
	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=93366
	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=88590 translate
	 * everything inbetween <scriptlet> tags, which may be more than one
	 * region (esp. CDATA)
	 * 
	 */
	private void translateXMLJSPContent(int type) {

		IStructuredDocumentRegion sdr = getCurrentNode().getNext();
		int start = sdr.getStartOffset();
		int end = sdr.getEndOffset();
		String sdrText = ""; //$NON-NLS-1$

		StringBuffer regionText = new StringBuffer();
		// read structured document regions until </jsp:scriptlet> or EOF
		while (sdr != null && sdr.getType() != DOMRegionContext.XML_TAG_NAME) {

			// setup for next region
			if (regionText.length() == 0)
				start = sdr.getStartOffset();
			sdrText = sdr.getText();

			if (sdr.getType() == DOMRegionContext.XML_CDATA_TEXT) {
				// Clear out the buffer
				if (regionText.length() > 0) {
					writeToBuffer(type, regionText.toString(), start, end);
					regionText = new StringBuffer();
				}
				// just to be safe, make sure CDATA start & end are there
				if (sdrText.startsWith("<![CDATA[") && sdrText.endsWith("]]>")) { //$NON-NLS-1$ //$NON-NLS-2$

					start = sdr.getStartOffset() + 9; // <![CDATA[
					end = sdr.getEndOffset() - 3; // ]]>
					sdrText = sdrText.substring(9, sdrText.length() - 3);
					writeToBuffer(type, sdrText, start, end);
				}
			}
			else {
				// handle entity references
				regionText.append(EscapedTextUtil.getUnescapedText(sdrText));
				end = sdr.getEndOffset();
			}
			sdr = sdr.getNext();
		}

		if (regionText.length() > 0)
			writeToBuffer(type, regionText.toString(), start, end);
		setCurrentNode(sdr);
		setSourceReferencePoint();
	}

	private void writeToBuffer(int type, String content, int jspStart, int jspEnd) {
		switch (type) {
			case SCRIPTLET :
				translateScriptletString(content, getCurrentNode(), jspStart, jspEnd - jspStart, false);
				break;
			case EXPRESSION :
				translateExpressionString(content, getCurrentNode(), jspStart, jspEnd - jspStart, false);
				break;
			case DECLARATION :
				translateDeclarationString(content, getCurrentNode(), jspStart, jspEnd - jspStart, false);
				break;
		}
	}

	/**
	 * goes through comment regions, checks if any are an embedded JSP
	 * container if it finds one, it's sends the container into the
	 * translation routine
	 */
	protected void translateXMLCommentNode(IStructuredDocumentRegion node) {
		Iterator it = node.getRegions().iterator();
		ITextRegion commentRegion = null;
		while (it != null && it.hasNext()) {
			commentRegion = (ITextRegion) it.next();
			if (commentRegion instanceof ITextRegionContainer) {
				translateRegionContainer((ITextRegionContainer) commentRegion, EMBEDDED_JSP); // it's
				// embedded
				// jsp...iterate
				// regions...
			}
			else if (DOMRegionContext.XML_COMMENT_TEXT.equals(commentRegion.getType())) {
				// https://bugs.eclipse.org/bugs/show_bug.cgi?id=222215
				// support custom tags hidden in a comment region
				decodeScriptBlock(node.getFullText(commentRegion), node.getStartOffset(commentRegion));
			}
		}
	}

	/**
	 * determines which type of JSP node to translate
	 */
	protected void translateJSPNode(ITextRegion region, Iterator regions, String type, int JSPType) {
		if (type == DOMJSPRegionContexts.JSP_DIRECTIVE_OPEN && regions != null) {
			translateDirective(regions);
		}
		else {
			ITextRegionCollection contentRegion = null;
			if (JSPType == STANDARD_JSP && (setCurrentNode(getCurrentNode().getNext())) != null) {
				contentRegion = getCurrentNode();
			}
			else if (JSPType == EMBEDDED_JSP && region instanceof ITextRegionCollection) {
				translateEmbeddedJSPInBlock((ITextRegionCollection) region, regions);
				// ensure the rest of this method won't be called
			}
			/* NOTE: the type here is of the node preceding the current node
			 * thus must check to see if the current node is JSP close, if it is
			 * then the JSP is something akin to <%%> and should not be translated
			 * (Bug 189318)
			 */
			if (contentRegion != null && contentRegion.getType() != DOMJSPRegionContexts.JSP_CLOSE) {
				if (type == DOMJSPRegionContexts.JSP_EXPRESSION_OPEN) {
					translateExpression(contentRegion);
				}
				else if (type == DOMJSPRegionContexts.JSP_DECLARATION_OPEN) {
					translateDeclaration(contentRegion);
				}
				else if (type == DOMJSPRegionContexts.JSP_CONTENT || type == DOMJSPRegionContexts.JSP_SCRIPTLET_OPEN) {
					translateScriptlet(contentRegion);
				}
			}
			else {
				// this is the case of an attribute w/ no region <p
				// align="<%%>">
				setCursorOwner(getJSPTypeForRegion(region));
			}
		}
	}


	private void translateEL(String elText, String delim, IStructuredDocumentRegion currentNode, int contentStart, int contentLength) {
		IJSPELTranslator translator = getELTranslator();
		if (null != translator) {
			List elProblems = translator.translateEL(elText, delim, currentNode, contentStart, contentLength, fUserELExpressions, fUserELRanges, fStructuredDocument);
			fTranslationProblems.addAll(elProblems);
		}
	}

	/**
	 * Discover and instantiate an EL translator.
	 */
	public IJSPELTranslator getELTranslator() {
		if (fELTranslator == null) {

			/*
			 * name of plugin that exposes this extension point
			 */
			IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(JSP_CORE_PLUGIN_ID, EL_TRANSLATOR_EXTENSION_NAME); // -
			// extension
			// id

			// Iterate over all declared extensions of this extension point.
			// A single plugin may extend the extension point more than once,
			// although it's not recommended.
			IConfigurationElement bestTranslator = null;
			IExtension[] extensions = extensionPoint.getExtensions();
			for (int curExtension = 0; curExtension < extensions.length; curExtension++) {
				IExtension extension = extensions[curExtension];

				IConfigurationElement[] translators = extension.getConfigurationElements();
				for (int curTranslator = 0; curTranslator < translators.length; curTranslator++) {

					IConfigurationElement elTranslator = translators[curTranslator];

					if (!EL_TRANSLATOR_EXTENSION_NAME.equals(elTranslator.getName())) { // -
						// name
						// of
						// configElement
						continue;
					}

					String idString = elTranslator.getAttribute("id"); //$NON-NLS-1$
					if (null != idString && idString.equals(fELTranslatorID) || (null == bestTranslator && DEFAULT_JSP_EL_TRANSLATOR_ID.equals(idString))) {
						bestTranslator = elTranslator;
					}
				}
			}

			if (null != bestTranslator) {
				try {
					Object execExt = bestTranslator.createExecutableExtension("class"); //$NON-NLS-1$
					if (execExt instanceof IJSPELTranslator) {
						return fELTranslator = (IJSPELTranslator) execExt;
					}
				}
				catch (CoreException e) {
					Logger.logException(e);
				}
			}
		}
		return fELTranslator;
	}

	/**
	 * Pass the ITextRegionCollection which is the embedded region
	 * 
	 * @param regions
	 *            iterator for collection
	 */
	private void translateEmbeddedJSPInBlock(ITextRegionCollection collection, Iterator regions) {
		ITextRegion region = null;
		while (regions.hasNext()) {
			region = (ITextRegion) regions.next();
			if (isJSP(region.getType()))
				break;
			region = null;
		}
		if (region != null) {
			translateEmbeddedJSPInAttribute(collection);
			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=126377
			// all of collection was translated so just finish off iterator
			while (regions.hasNext())
				regions.next();
		}
	}

	/*
	 * Translates all embedded jsp regions in embeddedContainer for example:
	 * <a href="index.jsp?p=<%=abc%>b=<%=xyz%>">abc</a>
	 */
	private void translateEmbeddedJSPInAttribute(ITextRegionCollection embeddedContainer) {
		// THIS METHOD IS A FIX FOR
		// jsp embedded in attribute regions
		// loop all regions
		ITextRegionList embeddedRegions = embeddedContainer.getRegions();
		ITextRegion delim = null;
		ITextRegion content = null;
		String type = null;
		String quotetype = null;
		for (int i = 0; i < embeddedRegions.size(); i++) {

			// possible delimiter, check later
			delim = embeddedRegions.get(i);
			type = delim.getType();
			if (type == DOMRegionContext.XML_TAG_NAME ) {
				String fullTagName = embeddedContainer.getText(delim);
				if (fullTagName.indexOf(':') > -1 && !fullTagName.startsWith(JSP_PREFIX)) {
					ITextRegion prevRegion =null;
					if (i>0)
						prevRegion = embeddedRegions.get(i-1);
					addCustomTaglibVariables(fullTagName, embeddedContainer,prevRegion,i+1); // it may be a custom tag
				}
			}
			if(type == DOMJSPRegionContexts.XML_TAG_ATTRIBUTE_VALUE_DQUOTE || type == DOMJSPRegionContexts.XML_TAG_ATTRIBUTE_VALUE_SQUOTE
				|| type == DOMJSPRegionContexts.JSP_TAG_ATTRIBUTE_VALUE_DQUOTE || type == DOMJSPRegionContexts.JSP_TAG_ATTRIBUTE_VALUE_SQUOTE)
				quotetype = type;

			// check next region to see if it's content
			if (i + 1 < embeddedRegions.size()) {
				String regionType = embeddedRegions.get(i + 1).getType();
				if (regionType == DOMJSPRegionContexts.JSP_CONTENT || regionType == DOMJSPRegionContexts.JSP_EL_CONTENT)
					content = embeddedRegions.get(i + 1);
			}

			if (content != null) {
				int contentStart = embeddedContainer.getStartOffset(content);
				int rStart = fCurrentNode.getStartOffset() + contentStart;
				int rEnd = fCurrentNode.getStartOffset() + embeddedContainer.getEndOffset(content);

				boolean inThisRegion = rStart <= fSourcePosition && rEnd >= fSourcePosition;
				// int jspPositionStart = fCurrentNode.getStartOffset() +
				// contentStart;

				if (type == DOMJSPRegionContexts.JSP_EXPRESSION_OPEN) {
					fLastJSPType = EXPRESSION;
					// translateExpressionString(embeddedContainer.getText(content),
					// fCurrentNode, contentStart, content.getLength());
					translateExpressionString(embeddedContainer.getText(content), embeddedContainer, contentStart, content.getLength(), quotetype);
				}
				else if (type == DOMJSPRegionContexts.JSP_SCRIPTLET_OPEN) {
					fLastJSPType = SCRIPTLET;
					// translateScriptletString(embeddedContainer.getText(content),
					// fCurrentNode, contentStart, content.getLength());
					translateScriptletString(embeddedContainer.getText(content), embeddedContainer, contentStart, content.getLength(), false);
				}
				else if (type == DOMJSPRegionContexts.JSP_DECLARATION_OPEN) {
					fLastJSPType = DECLARATION;
					// translateDeclarationString(embeddedContainer.getText(content),
					// fCurrentNode, contentStart, content.getLength());
					translateDeclarationString(embeddedContainer.getText(content), embeddedContainer, contentStart, content.getLength(), false);
				}
				else if (type == DOMJSPRegionContexts.JSP_EL_OPEN) {
					fLastJSPType = EXPRESSION;
					translateEL(embeddedContainer.getText(content), embeddedContainer.getText(delim), fCurrentNode, contentStart, content.getLength());
				}

				// calculate relative offset in buffer
				if (inThisRegion) {
					setCursorOwner(fLastJSPType);
					int currentBufferLength = getCursorOwner().length();
					setRelativeOffset((fSourcePosition - contentStart) + currentBufferLength);
					if (fLastJSPType == EXPRESSION) {
						// if an expression, add then length of the enclosing
						// paren..
						setCursorInExpression(true);
						setRelativeOffset(getRelativeOffset() + EXPRESSION_PREFIX.length());
					}
				}
			}
			else {
				type = null;
			}
		}
	}

	private int fLastJSPType = SCRIPTLET;

	/**
	 * JSPType is only used internally in this class to describe tye type of
	 * region to be translated
	 * 
	 * @param region
	 * @return int
	 */
	private int getJSPTypeForRegion(ITextRegion region) {
		String regionType = region.getType();
		int type = SCRIPTLET;
		if (regionType == DOMJSPRegionContexts.JSP_SCRIPTLET_OPEN)
			type = SCRIPTLET;
		else if (regionType == DOMJSPRegionContexts.JSP_EXPRESSION_OPEN)
			type = EXPRESSION;
		else if (regionType == DOMJSPRegionContexts.JSP_DECLARATION_OPEN)
			type = DECLARATION;
		else if (regionType == DOMJSPRegionContexts.JSP_CONTENT)
			type = fLastJSPType;
		// remember the last type, in case the next type that comes in is
		// JSP_CONTENT
		fLastJSPType = type;
		return type;
	}

	/**
	 * /* <%@ %> /* need to pass in the directive tag region
	 */
	protected void translateDirective(Iterator regions) {
		ITextRegion r = null;
		String regionText, attrValue = ""; //$NON-NLS-1$
		while (regions.hasNext() && (r = (ITextRegion) regions.next()) != null && r.getType() == DOMJSPRegionContexts.JSP_DIRECTIVE_NAME) { // could
			// be
			// XML_CONTENT
			// =
			// "",
			// skips
			// attrs?
			regionText = getCurrentNode().getText(r);
			if (regionText.equals("taglib")) { //$NON-NLS-1$
				// add custom tag block markers here
				handleTaglib();
				return;
			}
			else if (regionText.equals("include")) { //$NON-NLS-1$
				String fileLocation = ""; //$NON-NLS-1$
				// CMVC 258311
				// PMR 18368, B663
				// skip to required "file" attribute, should be safe because
				// "file" is the only attribute for the include directive
				while (r != null && regions.hasNext() && !r.getType().equals(DOMRegionContext.XML_TAG_ATTRIBUTE_NAME)) {
					r = (ITextRegion) regions.next();
				}
				fileLocation = getAttributeValue(r, regions);
				if (attrValue != null)
					handleIncludeFile(fileLocation);
			}
			else if (regionText.equals("page")) { //$NON-NLS-1$
				translatePageDirectiveAttributes(regions, getCurrentNode());
			}
			else if (regionText.equals("tag")) { //$NON-NLS-1$
				// some attributes overlap, so both are handled in this method
				translatePageDirectiveAttributes(regions, getCurrentNode());
			}
			else if (regionText.equals("variable")) { //$NON-NLS-1$
				translateVariableDirectiveAttributes(regions);
			}
			else if (regionText.equals("attribute")) { //$NON-NLS-1$
				translateAttributeDirectiveAttributes(regions);
			}
		}
	}

	private void translateAttributeDirectiveAttributes(Iterator regions) {
		ITextRegion r = null;
		String attrName, attrValue;

		String varType = "java.lang.String"; //$NON-NLS-1$ // the default class...
		String varName = null;
		String description = "";//$NON-NLS-1$ 
		boolean isFragment = false;

		// iterate all attributes
		while (regions.hasNext() && (r = (ITextRegion) regions.next()) != null && r.getType() != DOMJSPRegionContexts.JSP_CLOSE) {
			attrName = attrValue = null;
			if (r.getType().equals(DOMRegionContext.XML_TAG_ATTRIBUTE_NAME)) {
				attrName = getCurrentNode().getText(r).trim();
				if (attrName.length() > 0) {
					if (regions.hasNext() && (r = (ITextRegion) regions.next()) != null && r.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) {
						if (regions.hasNext() && (r = (ITextRegion) regions.next()) != null && r.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
							attrValue = StringUtils.strip(getCurrentNode().getText(r));
						}
						// has equals, but no value?
					}
					if (attrName.equals(JSP11Namespace.ATTR_NAME_TYPE)) {
						varType = attrValue;
					}
					else if (attrName.equals(JSP20Namespace.ATTR_NAME_FRAGMENT)) {
						isFragment = Boolean.valueOf(attrValue).booleanValue();
					}
					else if (attrName.equals(JSP11Namespace.ATTR_NAME_NAME)) {
						varName = attrValue;
					}
					else if (attrName.equals(JSP20Namespace.ATTR_NAME_DESCRIPTION)) {
						description = attrValue;
					}
				}
			}
		}
		if (varName != null) {
			if (isFragment) {
				// 2.0:JSP.8.5.2
				varType = "javax.servlet.jsp.tagext.JspFragment"; //$NON-NLS-1$
			}
			String declaration = new TaglibVariable(varType, varName, "", description).getDeclarationString(true, TaglibVariable.M_PRIVATE); //$NON-NLS-1$
			appendToBuffer(declaration, fUserDeclarations, false, fCurrentNode);
		}
	}

	private void translateVariableDirectiveAttributes(Iterator regions) {
		/*
		 * Shouldn't create a scripting variable in *this* tag file's
		 * translation, only in JSP files that use it -
		 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=188780
		 */
	}

	/*
	 * This method should ideally only be called once per run through
	 * JSPTranslator This is intended for use by inner helper classes that
	 * need to add block markers to their own parsers. This method only adds
	 * markers that came from <@taglib> directives, (not <@include>), since
	 * include file taglibs are handled on the fly when they are encountered. *
	 * @param regions
	 * 
	 * @deprecated - does not properly handle prefixes
	 */
	protected void handleTaglib() {
		// get/create TLDCMDocument
		TLDCMDocumentManager mgr = TaglibController.getTLDCMDocumentManager(fStructuredDocument);
		if (mgr != null) {
			List trackers = mgr.getCMDocumentTrackers(getCurrentNode().getEnd());
			Iterator it = trackers.iterator();
			CMDocumentTracker tracker = null;
			Iterator taglibRegions = null;
			IStructuredDocumentRegion sdRegion = null;
			ITextRegion r = null;
			while (it.hasNext()) {
				tracker = (CMDocumentTracker) it.next();
				sdRegion = tracker.getStructuredDocumentRegion();
				// since may be call from another thread (like a background
				// job)
				// this check is to be safer
				if (sdRegion != null && !sdRegion.isDeleted()) {
					taglibRegions = sdRegion.getRegions().iterator();
					while (!sdRegion.isDeleted() && taglibRegions.hasNext()) {
						r = (ITextRegion) taglibRegions.next();
						if (r.getType().equals(DOMJSPRegionContexts.JSP_DIRECTIVE_NAME)) {
							String text = sdRegion.getText(r);
							if (JSP12TLDNames.TAGLIB.equals(text) || JSP12Namespace.ElementName.DIRECTIVE_TAGLIB.equals(text)) {
								addBlockMarkers(tracker.getDocument());
							}
						}
					}
				}
			}
		}
	}

	/*
	 * This method should ideally only be called once per run through
	 * JSPTranslator This is intended for use by inner helper classes that
	 * need to add block markers to their own parsers. This method only adds
	 * markers that came from <@taglib> directives, (not <@include>), since
	 * include file taglibs are handled on the fly when they are encountered. *
	 * @param regions
	 */
	private void handleTaglib(String prefix) {
		// get/create TLDCMDocument
		TLDCMDocumentManager mgr = TaglibController.getTLDCMDocumentManager(fStructuredDocument);
		if (mgr != null) {
			// get trackers for the CMDocuments enabled at this offset
			List trackers = mgr.getCMDocumentTrackers(getCurrentNode().getEnd());
			Iterator it = trackers.iterator();
			CMDocumentTracker tracker = null;
			while (it.hasNext()) {
				tracker = (CMDocumentTracker) it.next();
				addBlockMarkers(prefix + ":", tracker.getDocument()); //$NON-NLS-1$
			}
		}
	}

	/*
	 * adds block markers to JSPTranslator's block marker list for all
	 * elements in doc @param doc
	 */
	protected void addBlockMarkers(CMDocument doc) {
		if (doc.getElements().getLength() > 0) {
			Iterator elements = doc.getElements().iterator();
			CMNode node = null;
			while (elements.hasNext()) {
				node = (CMNode) elements.next();
				getBlockMarkers().add(new BlockMarker(node.getNodeName(), null, DOMJSPRegionContexts.JSP_CONTENT, true));
			}
		}
	}

	/*
	 * adds block markers to JSPTranslator's block marker list for all
	 * elements in doc @param doc
	 */
	protected void addBlockMarkers(String prefix, CMDocument doc) {
		if (doc.getElements().getLength() > 0) {
			Iterator elements = doc.getElements().iterator();
			CMNode node = null;
			while (elements.hasNext()) {
				node = (CMNode) elements.next();
				if (node instanceof TLDElementDeclaration && ((TLDElementDeclaration) node).getBodycontent().equals(JSP12TLDNames.CONTENT_TAGDEPENDENT))
					getBlockMarkers().add(new BlockMarker(prefix + node.getNodeName(), null, DOMRegionContext.BLOCK_TEXT, true));
				else
					getBlockMarkers().add(new BlockMarker(prefix + node.getNodeName(), null, DOMJSPRegionContexts.JSP_CONTENT, true));
			}
		}
	}

	/**
	 * If r is an attribute name region, this method will safely return the
	 * value for that attribute.
	 * 
	 * @param r
	 * @param remainingRegions
	 * @return the value for the attribute name (r), or null if isn't one
	 */
	protected String getAttributeValue(ITextRegion r, Iterator remainingRegions) {
		if (r.getType().equals(DOMRegionContext.XML_TAG_ATTRIBUTE_NAME)) {
			if (remainingRegions.hasNext() && (r = (ITextRegion) remainingRegions.next()) != null && r.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) {
				if (remainingRegions.hasNext() && (r = (ITextRegion) remainingRegions.next()) != null && r.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
					return StringUtils.stripQuotes(getCurrentNode().getText(r));
				}
			}
		}
		return null;
	}

	/**
	 * takes an iterator of the attributes of a page directive and the
	 * directive itself. The iterator is used in case it can be optimized, but
	 * the documentRegion is still required to ensure that the values are
	 * extracted from the correct text.
	 */
	protected void translatePageDirectiveAttributes(Iterator regions, IStructuredDocumentRegion documentRegion) {
		ITextRegion r = null;
		String attrName, attrValue;
		// iterate all attributes
		while (regions.hasNext() && (r = (ITextRegion) regions.next()) != null && r.getType() != DOMJSPRegionContexts.JSP_CLOSE) {
			attrName = attrValue = null;
			if (r.getType().equals(DOMRegionContext.XML_TAG_ATTRIBUTE_NAME)) {

				attrName = documentRegion.getText(r).trim();
				if (attrName.length() > 0) {
					if (regions.hasNext() && (r = (ITextRegion) regions.next()) != null && r.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) {
						if (regions.hasNext() && (r = (ITextRegion) regions.next()) != null && r.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {

							attrValue = StringUtils.strip(documentRegion.getText(r));
						}
						// has equals, but no value?
					}
					setDirectiveAttribute(attrName, attrValue);
				}
			}
		}
	}

	/**
	 * sets the appropriate page/tag directive attribute
	 */
	protected void setDirectiveAttribute(String attrName, String attrValue) {
		if (attrValue == null)
			return; // uses default (if there was one)
		if (attrName.equals("extends")) //$NON-NLS-1$
		{
			fSuperclass = attrValue;
		}
		else if (attrName.equals("import")) //$NON-NLS-1$
		{
			addImports(attrValue);
		}
		else if (attrName.equals("session")) //$NON-NLS-1$
		{
			fIsInASession = Boolean.valueOf(attrValue).booleanValue();
		}
		else if (attrName.equals("buffer")) //$NON-NLS-1$
		{
			// ignore for now
		}
		else if (attrName.equals("autoFlush")) //$NON-NLS-1$
		{
			// ignore for now
		}
		else if (attrName.equals("isThreadSafe")) //$NON-NLS-1$
		{
			// fThreadSafe = "true".equalsIgnoreCase(attrValue); //$NON-NLS-1$
		}
		else if (attrName.equals("isErrorPage")) //$NON-NLS-1$
		{
			fIsErrorPage = Boolean.valueOf(attrValue).booleanValue();
		}
	}

	protected void handleIncludeFile(String filename) {
		if (filename != null && fProcessIncludes) {
			IPath modelPath = getModelPath();
			IPath basePath = modelPath;
			if (basePath != null) {
				/*
				 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=227576
				 * 
				 * The resolution of the included fragment should use the file
				 * containing the directive as the base reference, not always
				 * the main JSP being invoked. Verified behavior with Apache
				 * Tomcat 5.5.20.
				 */
				if (!getIncludes().isEmpty()) {
					basePath = new Path((String) getIncludes().peek());
				}
				String filePathString = FacetModuleCoreSupport.resolve(basePath, filename).toString();
				fIncludedPaths.add(filePathString);

				if (!getIncludes().contains(filePathString) && !filePathString.equals(modelPath.toString())) {
					getIncludes().push(filePathString);
					JSPIncludeRegionHelper helper = new JSPIncludeRegionHelper(this, true);
					// Should we consider preludes on this segment?
					helper.parse(filePathString);
					getIncludes().pop();
				}
			}
		}
	}

	private Stack getIncludes() {
		if (fIncludes == null)
			fIncludes = new Stack();
		return fIncludes;
	}

	public Collection getIncludedPaths() {
		return fIncludedPaths;
	}

	protected void translateExpressionString(String newText, ITextRegionCollection embeddedContainer, int jspPositionStart, int jspPositionLength, boolean isIndirect) {
		appendToBuffer(EXPRESSION_PREFIX, fUserCode, false, embeddedContainer, true);
		appendToBuffer(newText, fUserCode, true, embeddedContainer, jspPositionStart, jspPositionLength, isIndirect, true);
		appendToBuffer(EXPRESSION_SUFFIX, fUserCode, false, embeddedContainer);
	}
	
	protected void translateExpressionString(String newText, ITextRegionCollection embeddedContainer, int jspPositionStart, int jspPositionLength, String quotetype) {
		if(quotetype == null || quotetype == DOMJSPRegionContexts.XML_TAG_ATTRIBUTE_VALUE_DQUOTE ||quotetype == DOMJSPRegionContexts.XML_TAG_ATTRIBUTE_VALUE_SQUOTE ) {
			translateExpressionString(newText, embeddedContainer, jspPositionStart, jspPositionLength, false);
			return;
		}

		//-- This is a quoted attribute. We need to unquote as per the JSP spec: JSP 2.0 page 1-36
		appendToBuffer(EXPRESSION_PREFIX, fUserCode, false, embeddedContainer, true);

		int length = newText.length();
		int runStart = 0;
		int i = 0;
		for ( ; i < length; i++) {
			//-- collect a new run
			char c = newText.charAt(i);
			if (c == '\\') {
				//-- Escaped value. Add the run, then unescape
				int runLength = i-runStart;
				if (runLength > 0) {
					appendToBuffer(newText.substring(runStart, i), fUserCode, true, embeddedContainer, jspPositionStart, runLength, true, true);
					jspPositionStart += runLength + 1;
					jspPositionLength -= runLength + 1;
				}
				runStart = ++i;
				if (i >= length) { // Escape but no data follows?!
					//- error.
					break;
				}
				c = newText.charAt(i);				// The escaped character, copied verbatim
			}
		}
		//-- Copy last-run
		int runLength = i - runStart;
		if (runLength > 0)
			appendToBuffer(newText.substring(runStart, i), fUserCode, true, embeddedContainer, jspPositionStart, runLength, true, false);
		appendToBuffer(EXPRESSION_SUFFIX, fUserCode, false, embeddedContainer);
	}

	protected void translateDeclarationString(String newText, ITextRegionCollection embeddedContainer, int jspPositionStart, int jspPositionLength, boolean isIndirect) {
		appendToBuffer(newText, fUserDeclarations, true, embeddedContainer, jspPositionStart, jspPositionLength, isIndirect);
		appendToBuffer(ENDL, fUserDeclarations, false, embeddedContainer);
	}

	/**
	 * used by XMLJSPRegionHelper for included JSP files
	 * 
	 * @param newText
	 * @param embeddedContainer
	 * @param jspPositionStart
	 * @param jspPositionLength
	 */
	protected void translateScriptletString(String newText, ITextRegionCollection embeddedContainer, int jspPositionStart, int jspPositionLength, boolean isIndirect) {
		appendToBuffer(newText, fUserCode, true, embeddedContainer, jspPositionStart, jspPositionLength, isIndirect);
	}

	// the following 3 methods determine the cursor position
	// <%= %>
	protected void translateExpression(ITextRegionCollection region) {
		String newText = getUnescapedRegionText(region, EXPRESSION);
		appendToBuffer(EXPRESSION_PREFIX, fUserCode, false, region, true);
		appendToBuffer(newText, fUserCode, true, region, true);
		appendToBuffer(EXPRESSION_SUFFIX, fUserCode, false, region);
	}

	//
	// <%! %>
	protected void translateDeclaration(ITextRegionCollection region) {
		String newText = getUnescapedRegionText(region, DECLARATION);
		appendToBuffer(newText, fUserDeclarations, true, region);
		appendToBuffer(ENDL, fUserDeclarations, false, region);
	}

	//
	// <% %>
	protected void translateScriptlet(ITextRegionCollection region) {
		String newText = getUnescapedRegionText(region, SCRIPTLET);
		appendToBuffer(newText, fUserCode, true, region);
	}

	/**
	 * Append using a region, probably indirect mapping (eg. <%@page
	 * include=""%>)
	 * 
	 * @param newText
	 * @param buffer
	 * @param addToMap
	 * @param jspReferenceRegion
	 */
	private void appendToBuffer(String newText, StringBuffer buffer, boolean addToMap, ITextRegionCollection jspReferenceRegion) {
		int start = 0, length = 0;
		if (jspReferenceRegion != null) {
			start = jspReferenceRegion.getStartOffset();
			length = jspReferenceRegion.getLength();
		}
		appendToBuffer(newText, buffer, addToMap, jspReferenceRegion, start, length, false);
	}
	
	/**
	 * Append using a region, probably indirect mapping (eg. <%@page
	 * include=""%>)
	 * 
	 * @param newText
	 * @param buffer
	 * @param addToMap
	 * @param jspReferenceRegion
	 * @param nonl
	 */
	private void appendToBuffer(String newText, StringBuffer buffer, boolean addToMap, ITextRegionCollection jspReferenceRegion, boolean nonl) {
		int start = 0, length = 0;
		if (jspReferenceRegion != null) {
			start = jspReferenceRegion.getStartOffset();
			length = jspReferenceRegion.getLength();
		}
		appendToBuffer(newText, buffer, addToMap, jspReferenceRegion, start, length, false, nonl);
	}
	
	private void appendToBuffer(String newText, StringBuffer buffer, boolean addToMap, ITextRegionCollection jspReferenceRegion, int jspPositionStart, int jspPositionLength, boolean isIndirect) {
		appendToBuffer(newText, buffer, addToMap, jspReferenceRegion, jspPositionStart, jspPositionLength, isIndirect, false);
	}


	/**
	 * Adds newText to the buffer passed in, and adds to translation mapping
	 * as specified by the addToMap flag. some special cases to consider (that
	 * may be affected by changes to this method): included files scriplets in
	 * an attribute value refactoring
	 * 
	 * @param newText
	 * @param buffer
	 * @param addToMap
	 */
	private void appendToBuffer(String newText, StringBuffer buffer, boolean addToMap, ITextRegionCollection jspReferenceRegion, int jspPositionStart, int jspPositionLength, boolean isIndirect, boolean nonl) {

		int origNewTextLength = newText.length();

		// nothing to append
		if (jspReferenceRegion == null)
			return;

		// add a newline so translation looks cleaner
		if (! nonl && !newText.endsWith(ENDL))
			newText += ENDL;

		//dump any non translated code before writing translated code
		writePlaceHolderForNonTranslatedCode();

		//if appending to the buffer can assume something got translated
		fCodeTranslated = true;

		if (buffer == fUserCode) {
			buffer.append(newText);
			if (addToMap) {
				if (isUsebeanTag(jspReferenceRegion)) {
					try {
						// requires special mapping
						appendUseBeanToBuffer(newText, jspReferenceRegion, isIndirect);
					}
					catch (Exception e) {
						// still working out kinks
						Logger.logException(e);
					}
				}
				else {
					// all other cases
					Position javaRange = new Position(fOffsetInUserCode, origNewTextLength);
					Position jspRange = new Position(jspPositionStart, jspPositionLength);

					fCodeRanges.put(javaRange, jspRange);
					if (isIndirect)
						fIndirectRanges.put(javaRange, jspRange);
				}
			}
			fOffsetInUserCode += newText.length();
		}
		else if (buffer == fUserDeclarations) {
			buffer.append(newText);
			if (addToMap) {
				Position javaRange = new Position(fOffsetInUserDeclarations, newText.length());
				Position jspRange = new Position(jspPositionStart, jspPositionLength);

				fDeclarationRanges.put(javaRange, jspRange);
				if (isIndirect)
					fIndirectRanges.put(javaRange, jspRange);
			}
			fOffsetInUserDeclarations += newText.length();
		}
	}

	/**
	 * 
	 * @param jspReferenceRegion
	 * @return
	 */
	private boolean isUsebeanTag(ITextRegionCollection jspReferenceRegion) {
		ITextRegionList regions = jspReferenceRegion.getRegions();
		ITextRegion r = null;
		boolean isUseBean = false;
		for (int i = 0; i < regions.size(); i++) {
			r = regions.get(i);
			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=128490
			// length of 11 is the length of jsp:useBean
			// and saves the expensive getText.equals call
			if (r.getType() == DOMRegionContext.XML_TAG_NAME) {
				if (r.getTextLength() == 11 && jspReferenceRegion.getText(r).equals("jsp:useBean")) { //$NON-NLS-1$
					isUseBean = true;
				}
				// break no matter what if you hit tagname
				break;
			}
		}
		return isUseBean;
	}

	/**
	 * @param importName
	 *            should be just the package plus the type eg. java.util.List
	 *            or java.util.*
	 * @param jspReferenceRegion
	 *            should be the <%@ page import = "java.util.List"%> region
	 * @param addToMap
	 */
	private void appendImportToBuffer(String importName, ITextRegionCollection jspReferenceRegion, boolean addToMap) {
		String javaImportString = "import " + importName + ";" + ENDL; //$NON-NLS-1$ //$NON-NLS-2$
		fUserImports.append(javaImportString);
		if (addToMap) {
			addImportToMap(importName, jspReferenceRegion);
		}
		fOffsetInUserImports += javaImportString.length();
	}

	/**
	 * new text can be something like: "import java.lang.Object;\n"
	 * 
	 * but the reference region could have been something like: <%@page
	 * import="java.lang.Object, java.io.*, java.util.List"%>
	 * 
	 * so the exact mapping has to be calculated carefully.
	 * 
	 * isIndirect means that the import came from an included file (if true)
	 * 
	 * @param importName
	 * @param jspReferenceRegion
	 */
	private void addImportToMap(String importName, ITextRegionCollection jspReferenceRegion) {

		// massage text
		// String jspText = importName.substring(importName.indexOf("import ")
		// + 7, importName.indexOf(';'));
		// String jspText = importName.trim();

		// these positions will be updated below
		Position javaRange = new Position(fOffsetInUserImports + 7, 1);
		Position jspRange = new Position(jspReferenceRegion.getStart(), jspReferenceRegion.getLength());

		// calculate JSP range by finding "import" attribute
		ITextRegionList regions = jspReferenceRegion.getRegions();
		int size = regions.size();

		int start = -1;
		int length = -1;

		ITextRegion r = null;
		for (int i = 0; i < size; i++) {
			r = regions.get(i);
			if (r.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME)
				if (jspReferenceRegion.getText(r).trim().equals("import")) { //$NON-NLS-1$
					// get the attr value region
					if (size > i + 2) {
						r = regions.get(i + 2);
						if (r.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {

							String jspImportText = jspReferenceRegion.getText(r);

							// the position in question (in the JSP) is what
							// is bracketed below
							// includes whitespace
							// <%@page import="java.lang.Object,[ java.io.* ],
							// java.util.List"%>

							// in the java file
							// import [ java.io.* ];

							start = jspImportText.indexOf(importName);
							length = importName.length();

							// safety, don't add to map if bad positioning
							if (start == -1 || length < 1)
								break;

							// update jsp range
							jspRange.setOffset(jspReferenceRegion.getStartOffset(r) + start);
							jspRange.setLength(length);

							// update java range
							javaRange.setLength(length);

							break;
						}
					}
				}
		}

		// safety for bad ranges
		if (start != -1 && length > 1) {
			// put ranges in java -> jsp range map
			fImportRanges.put(javaRange, jspRange);
		}
	}

	/**
	 * temp fix for 282295 until better mapping is in place
	 * 
	 * @param newText
	 * @param jspReferenceRegion
	 */
	private void appendUseBeanToBuffer(String newText, ITextRegionCollection jspReferenceRegion, boolean isIndirect) throws Exception {
		// java string looks like this (tokenized)
		// Type id = new Classname();\n
		// 0 1 2 3 4
		// or
		// Type id = null;\n // if there is no classname
		// 0 1 2 3

		// ----------------------
		// calculate java ranges
		// ----------------------
		StringTokenizer st = new StringTokenizer(newText, " ", false); //$NON-NLS-1$
		int i = 0;
		String[] parsedJava = new String[st.countTokens()];
		while (st.hasMoreTokens())
			parsedJava[i++] = st.nextToken();

		String type = parsedJava[0] != null ? parsedJava[0] : ""; //$NON-NLS-1$
		String id = parsedJava[1] != null ? parsedJava[1] : ""; //$NON-NLS-1$
		String className = parsedJava.length > 4 ? parsedJava[4] : ""; //$NON-NLS-1$

		Position javaTypeRange = new Position(fOffsetInUserCode, type.length());
		Position javaIdRange = new Position(fOffsetInUserCode + type.length() + 1, id.length());
		Position javaClassRange = new Position(fOffsetInUserCode + type.length() + 1 + id.length() + 7, 0);
		/*
		 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=212242 - Check for
		 * the existence of '(' first.
		 */
		int parenPos = -1;
		if (className.length() >= 4 && (parenPos = className.indexOf('(')) >= 0) {
			// https://bugs.eclipse.org/bugs/show_bug.cgi?id=86132
			int classNameLength = className.substring(0, parenPos).length();
			javaClassRange = new Position(fOffsetInUserCode + type.length() + 1 + id.length() + 7, classNameLength);
		}

		// ---------------------
		// calculate jsp ranges
		// ---------------------
		ITextRegionList regions = jspReferenceRegion.getRegions();
		ITextRegion r = null;
		String attrName = "", attrValue = ""; //$NON-NLS-1$ //$NON-NLS-2$
		int quoteOffset = 0;
		Position jspTypeRange = null;
		Position jspIdRange = null;
		Position jspClassRange = null;

		for (int j = 0; j < regions.size(); j++) {
			r = regions.get(j);
			if (r.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
				attrName = jspReferenceRegion.getText(r);
				if (regions.size() > j + 2 && regions.get(j + 2).getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
					// get attr value
					r = regions.get(j + 2);
					attrValue = jspReferenceRegion.getText(r);

					// may have quotes
					quoteOffset = (attrValue.startsWith("\"") || attrValue.startsWith("'")) ? 1 : 0; //$NON-NLS-1$ //$NON-NLS-2$

					if (attrName.equals("type")) //$NON-NLS-1$
						jspTypeRange = new Position(jspReferenceRegion.getStartOffset(r) + quoteOffset, StringUtils.stripQuotesLeaveInsideSpace(attrValue).length());
					else if (attrName.equals("id")) //$NON-NLS-1$
						jspIdRange = new Position(jspReferenceRegion.getStartOffset(r) + quoteOffset, StringUtils.stripQuotesLeaveInsideSpace(attrValue).length());
					else if (attrName.equals("class")) //$NON-NLS-1$
						jspClassRange = new Position(jspReferenceRegion.getStartOffset(r) + quoteOffset, StringUtils.stripQuotesLeaveInsideSpace(attrValue).length());
				}
			}
		}

		// put ranges in java -> jsp range map
		if (!type.equals("") && jspTypeRange != null) { //$NON-NLS-1$
			fCodeRanges.put(javaTypeRange, jspTypeRange);
			// note: don't update offsets for this map when result is built
			// they'll be updated when code ranges offsets are updated
			fUseBeanRanges.put(javaTypeRange, jspTypeRange);
			if (isIndirect)
				fIndirectRanges.put(javaTypeRange, jspTypeRange);
		}
		if (!id.equals("") && jspIdRange != null) { //$NON-NLS-1$
			fCodeRanges.put(javaIdRange, jspIdRange);
			// note: don't update offsets for this map when result is built
			// they'll be updated when code ranges offsets are updated
			fUseBeanRanges.put(javaIdRange, jspTypeRange);
			if (isIndirect)
				fIndirectRanges.put(javaIdRange, jspTypeRange);
		}
		if (!className.equals("") && jspClassRange != null) { //$NON-NLS-1$
			fCodeRanges.put(javaClassRange, jspClassRange);
			// note: don't update offsets for this map when result is built
			// they'll be updated when code ranges offsets are updated
			fUseBeanRanges.put(javaClassRange, jspTypeRange);
			if (isIndirect)
				fIndirectRanges.put(javaClassRange, jspTypeRange);
		}
	}

	/**
	 * Set the buffer to the current JSPType: STANDARD_JSP, EMBEDDED_JSP,
	 * DECLARATION, EXPRESSION, SCRIPTLET (for keepting track of cursor
	 * position when the final document is built)
	 * 
	 * @param JSPType
	 *            the JSP type that the cursor is in
	 */
	protected void setCursorOwner(int JSPType) {
		switch (JSPType) {
			case DECLARATION :
				setCursorOwner(fUserDeclarations);
				break;
			case EXPRESSION :
			case SCRIPTLET :
				setCursorOwner(fUserCode);
				break;
			default :
				setCursorOwner(fUserCode);
		}
	}

	/**
	 * this piece of code iterates through fCurrentNodes and clumps them
	 * together in a big text string - unescaping characters if they are not
	 * CDATA - simply appending if they are CDATA it stops iteration when it
	 * hits a node that is an XML_TAG_NAME (which should be the region closing
	 * tag)
	 */
	protected String getUnescapedRegionText(ITextRegionCollection stRegion, int JSPType) {
		StringBuffer buffer = new StringBuffer();
		int start = stRegion.getStartOffset();
		int end = stRegion.getEndOffset();
		// adjustment necessary for embedded region containers
		if (stRegion instanceof ITextRegionContainer && stRegion.getType() == DOMRegionContext.BLOCK_TEXT) {
			if (stRegion.getRegions() != null && stRegion.getRegions().size() > 1) {
				ITextRegion jspContent = stRegion.getRegions().get(1); // should
				// be
				// jspContent
				// region
				start = stRegion.getStartOffset(jspContent);
				end = stRegion.getEndOffset(jspContent);
			}
		}
		int CDATAOffset = 0; // number of characters lost in conversion
		int bufferSize = 0;
		if (stRegion.getType() == DOMJSPRegionContexts.JSP_CONTENT || stRegion.getType() == DOMRegionContext.BLOCK_TEXT // need
					// this
					// for
					// embedded
					// JSP
					// regions
					|| stRegion.getType() == DOMRegionContext.XML_TAG_NAME) // need
		// this
		// in
		// case
		// there's
		// no
		// region...
		{
			fInCodeRegion = (start <= fSourcePosition && fSourcePosition <= end);
			if (fInCodeRegion) {
				setCursorOwner(JSPType);
				setRelativeOffset((fSourcePosition - start) + getCursorOwner().length());
				if (JSPType == EXPRESSION) {
					// if an expression, add then length of the enclosing
					// paren..
					setCursorInExpression(true);
					setRelativeOffset(getRelativeOffset() + EXPRESSION_PREFIX.length());
				}
			}
			ITextRegion jspContent = null;
			if (stRegion.getRegions() != null && stRegion.getRegions().size() > 1)
				jspContent = stRegion.getRegions().get(1);
			return (jspContent != null) ? stRegion.getFullText(jspContent) : stRegion.getFullText(); // don't
			// unescape
			// if
			// it's
			// not
			// an
			// XMLJSP
			// tag
		}
		else if (stRegion.getType() == DOMJSPRegionContexts.JSP_CLOSE) {
			// need to determine cursor owner so that the fCurosorPosition
			// will be
			// correct even if there is no region after the cursor in the JSP
			// file
			setCursorOwner(JSPType);
		}
		// iterate XMLCONTENT and CDATA regions
		// loop fCurrentNode until you hit </jsp:scriptlet> (or other closing
		// tag name)
		while (getCurrentNode() != null && getCurrentNode().getType() != DOMRegionContext.XML_TAG_NAME && getCurrentNode().getType() != DOMJSPRegionContexts.JSP_CLOSE) // need to stop on the ending tag name...
		{
			start = getCurrentNode().getStartOffset();
			end = getCurrentNode().getEndOffset();
			bufferSize = buffer.length();
			CDATAOffset = unescapeRegion(getCurrentNode(), buffer);
			fInCodeRegion = (start <= fSourcePosition && fSourcePosition <= end);
			if (fInCodeRegion) {
				setCursorOwner(JSPType);
				// this offset is sort of complicated...
				// it's composed of:
				// 1. the length of the start of the current region up till
				// where the cursor is
				// 2. minus the number of characters lost in CDATA translation
				// 3. plus the length of the escaped buffer before the current
				// region, but
				// is still within the jsp tag
				setRelativeOffset((fSourcePosition - getCurrentNode().getStartOffset()) + getCursorOwner().length() - CDATAOffset + bufferSize);
				if (JSPType == EXPRESSION) {
					setCursorInExpression(true);
					// if an expression, add then length of the enclosing
					// paren..
					setRelativeOffset(getRelativeOffset() + EXPRESSION_PREFIX.length());
				}
			}
			if (getCurrentNode() != null)
				advanceNextNode();
		}
		return buffer.toString();
	}

	/**
	 * @param r
	 *            the region to be unescaped (XMLContent, XML ENTITY
	 *            REFERENCE, or CDATA)
	 * @param sb
	 *            the stringbuffer to append the text to
	 * @return the number of characters removed in unescaping this text
	 */
	protected int unescapeRegion(ITextRegion r, StringBuffer sb) {
		String s = ""; //$NON-NLS-1$
		int lengthBefore = 0, lengthAfter = 0, cdata_tags_length = 0;
		if (r != null && (r.getType() == DOMRegionContext.XML_CONTENT || r.getType() == DOMRegionContext.XML_ENTITY_REFERENCE)) {
			lengthBefore = (getCurrentNode() != r) ? getCurrentNode().getFullText(r).length() : getCurrentNode().getFullText().length();
			s = EscapedTextUtil.getUnescapedText(getCurrentNode(), r);
			lengthAfter = s.length();
			sb.append(s);
		}
		else if (r != null && r.getType() == DOMRegionContext.XML_CDATA_TEXT) {
			if (r instanceof ITextRegionContainer) // only interested in
			// contents
			{
				// navigate to next region container (which should be a JSP
				// region)
				Iterator it = ((ITextRegionContainer) r).getRegions().iterator();
				ITextRegion temp = null;
				while (it.hasNext()) {
					temp = (ITextRegion) it.next();
					if (temp instanceof ITextRegionContainer || temp.getType() == DOMRegionContext.XML_CDATA_TEXT) {
						sb.append(getCurrentNode().getFullText(temp));
					}
					else if (temp.getType() == DOMRegionContext.XML_CDATA_OPEN || temp.getType() == DOMRegionContext.XML_CDATA_CLOSE) {
						cdata_tags_length += temp.getLength();
					}
				}
			}
		}
		return (lengthBefore - lengthAfter + cdata_tags_length);
	}

	//
	// <jsp:useBean>
	protected void translateUseBean(ITextRegionCollection container) {
		ITextRegion r = null;
		String attrName = null;
		String attrValue = null;
		String id = null;
		ITextRegion idRegion = null;
		String type = null;
		ITextRegion typeRegion = null;
		String className = null;
		ITextRegion classnameRegion = null;
		String beanName = null;
		ITextRegion beanNameRegion = null;

		if (DOMRegionContext.XML_END_TAG_OPEN.equals(container.getFirstRegion().getType())) {
			if (!fUseBeansStack.isEmpty()) {
				fUseBeansStack.pop();
				appendToBuffer("}", fUserCode, false, fCurrentNode); //$NON-NLS-1$ 
			}
			else {
				// no useBean start tag being remembered
				ITextRegionCollection extraEndRegion = container;
				IJSPProblem missingStartTag = createJSPProblem(IJSPProblem.UseBeanStartTagMissing, IJSPProblem.F_PROBLEM_ID_LITERAL, NLS.bind(JSPCoreMessages.JSPTranslator_4,JSP11Namespace.ElementName.USEBEAN), extraEndRegion.getStartOffset(), extraEndRegion.getEndOffset());
				fTranslationProblems.add(missingStartTag);
			}
			return;
		}

		Iterator regions = container.getRegions().iterator();
		while (regions.hasNext() && (r = (ITextRegion) regions.next()) != null && (r.getType() != DOMRegionContext.XML_TAG_CLOSE || r.getType() != DOMRegionContext.XML_EMPTY_TAG_CLOSE)) {
			attrName = attrValue = null;
			if (r.getType().equals(DOMRegionContext.XML_TAG_ATTRIBUTE_NAME)) {
				attrName = container.getText(r).trim();
				if (regions.hasNext() && (r = (ITextRegion) regions.next()) != null && r.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_EQUALS) {
					if (regions.hasNext() && (r = (ITextRegion) regions.next()) != null && r.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) {
						attrValue = StringUtils.stripQuotes(container.getText(r));
					}
					// has equals, but no value?
				}
				// an attribute with no equals?
			}
			// (pa) might need different logic here if we wanna support more
			if (attrName != null && attrValue != null) {
				if (attrName.equals("id")) {//$NON-NLS-1$
					id = attrValue;
					idRegion = r;
				}
				else if (attrName.equals("class")) {//$NON-NLS-1$
					className = attrValue;
					classnameRegion = r;
				}
				else if (attrName.equals("type")) {//$NON-NLS-1$
					type = attrValue;
					typeRegion = r;
				}
				else if (attrName.equals("beanName")) { //$NON-NLS-1$
					beanName = attrValue;
					beanNameRegion = r;
				}
			}
		}

		if (id != null) {
			// The id is not a valid Java identifier
			if (!isValidJavaIdentifier(id) && idRegion != null) {
				Object problem = createJSPProblem(IJSPProblem.UseBeanInvalidID, IProblem.ParsingErrorInvalidToken, MessageFormat.format(JSPCoreMessages.JSPTranslator_0, new String[]{id}), container.getStartOffset(idRegion), container.getTextEndOffset(idRegion) - 1);
				fTranslationProblems.add(problem);
			}
			// No Type information is provided
			if (((type == null && className == null) || (type == null && beanName != null)) && idRegion != null) {
				Object problem = createJSPProblem(IJSPProblem.UseBeanMissingTypeInfo, IProblem.UndefinedType, NLS.bind(JSPCoreMessages.JSPTranslator_3, new String[]{id}), container.getStartOffset(idRegion), container.getTextEndOffset(idRegion) - 1);
				fTranslationProblems.add(problem);
			}
			// Cannot specify both a class and a beanName
			if (className != null && beanName != null && beanNameRegion != null) {
				ITextRegion nameRegion = container.getRegions().get(1);
				Object problem = createJSPProblem(IJSPProblem.UseBeanAmbiguousType, IProblem.AmbiguousType, JSPCoreMessages.JSPTranslator_2, container.getStartOffset(nameRegion), container.getTextEndOffset(nameRegion) - 1);
				fTranslationProblems.add(problem);
			}
			/*
			 * Only have a class or a beanName at this point, and potentially
			 * a type has id w/ type and/or classname/beanName
			 */
			// Type id = new Classname/Beanname();
			// or
			// Type id = null; // if there is no classname or beanname
			if ((type != null || className != null)) {
				if (className != null)
					className = decodeType(className);

				if (type == null) {
					type = className;
					typeRegion = classnameRegion;
				}
				else
					type = decodeType(type);

				/* Now check the types (multiple of generics may be involved) */
				List errorTypeNames = new ArrayList(2);
				if (!isTypeFound(type, errorTypeNames)) {
					for (int i = 0; i < errorTypeNames.size(); i++) {
						Object problem = createJSPProblem(IJSPProblem.F_PROBLEM_ID_LITERAL, IProblem.UndefinedType, MessageFormat.format(JSPCoreMessages.JSPTranslator_1, new String[]{errorTypeNames.get(i).toString()}), container.getStartOffset(typeRegion), container.getTextEndOffset(typeRegion) - 1);
						fTranslationProblems.add(problem);
					}
				}
				else {
					String prefix = type + " " + id + " = "; //$NON-NLS-1$ //$NON-NLS-2$
					String suffix = "null;" + ENDL; //$NON-NLS-1$
					if (className != null)
						suffix = "new " + className + "();" + ENDL; //$NON-NLS-1$ //$NON-NLS-2$
					else if (beanName != null)
						suffix = "(" + type + ") java.beans.Beans.instantiate(getClass().getClassLoader(), \"" + beanName + "\");" + ENDL; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
					appendToBuffer(prefix + suffix, fUserCode, true, fCurrentNode);
				}
			}
		}
		/*
		 * Add a brace and remember the start tag regardless of whether a
		 * variable was correctly created
		 */
		if (!DOMRegionContext.XML_EMPTY_TAG_CLOSE.equals(container.getLastRegion().getType())) {
			fUseBeansStack.push(container);
			appendToBuffer("{", fUserCode, false, fCurrentNode); //$NON-NLS-1$ 
		}
	}

	/**
	 * Decodes type strings for XML-style JSPs
	 * 
	 * @param type the string to decode
	 * @return the decoded string
	 */
	private String decodeType(String type) {
		final int length = type.length();
		final StringBuffer buffer = new StringBuffer(length);
		for (int i = 0; i < length; i++) {
			final char c = type.charAt(i);
			if (c == '&') {
				if (length > i + 3) {
					final String code = type.substring(i + 1, i + 4);
					final boolean isGt = "gt;".equals(code); //$NON-NLS-1$
					if (isGt || "lt;".equals(code)) { //$NON-NLS-1$
						i+=3;
						buffer.append(isGt ? '>' : '<');
						continue;
					}
				}
			}
			buffer.append(c);
		}
		return buffer.toString();
	}

	/**
	 * @param type
	 * @return
	 */
	private boolean isTypeFound(String rawTypeValue, List errorTypeNames) {
		IFile file = getFile();
		if(file == null)
			return true;
		
		IProject project = file.getProject();
		IJavaProject p = JavaCore.create(project);
		if (p.exists()) {
			String types[] = new String[3];
			if (rawTypeValue.indexOf('<') > 0) {
				// JSR 14 : Generics are being used, parse them out
				try {
					StringTokenizer toker = new StringTokenizer(rawTypeValue);
					// generic
					types[0] = toker.nextToken("<"); //$NON-NLS-1$
					// type 1 or key
					types[1] = toker.nextToken(",>"); //$NON-NLS-1$
					// type 2 or value
					types[2] = toker.nextToken(",>"); //$NON-NLS-1$
				}
				catch (NoSuchElementException e) {
					// StringTokenizer failure with unsupported syntax
				}
			}
			else {
				types[0] = rawTypeValue;
			}

			for (int i = 0; i < types.length; i++) {
				if (types[i] != null) {
					// remove any array suffixes 
					if (types[i].indexOf('[') > 0) {
						types[i] = types[i].substring(0, types[i].indexOf('['));
					}
					// remove any "extends" prefixes (JSR 14)
					if (types[i].indexOf("extends") > 0) { //$NON-NLS-1$
						types[i] = StringUtils.strip(types[i].substring(types[i].indexOf("extends"))); //$NON-NLS-1$
					}

					addNameToListIfTypeNotFound(p, types[i], errorTypeNames);
				}
			}
		}
		return errorTypeNames.isEmpty();
	}
	
	private void addNameToListIfTypeNotFound(IJavaProject p, String typeName, List collectedNamesNotFound) {
		try {
			if (typeName != null) {
				IType type = p.findType(typeName);
				if (type == null || !type.exists()) {
					collectedNamesNotFound.add(typeName);
				}
				else {
					IResource typeResource = type.getResource();
					if(typeResource != null) {
						
					}
				}
			}
		}
		catch (JavaModelException e) {
			// Not a Java Project
		}
	}

	private boolean isValidJavaIdentifier(String id) {
		char[] idChars = id.toCharArray();
		if (idChars.length < 1)
			return false;
		boolean isValid = Character.isJavaIdentifierStart(idChars[0]);
		for (int i = 1; i < idChars.length; i++) {
			isValid = isValid && Character.isJavaIdentifierPart(idChars[i]);
		}
		return isValid;
	}

	final public int getCursorPosition() {
		return fCursorPosition;
	}

	protected boolean isCursorInExpression() {
		return fCursorInExpression;
	}

	protected void setCursorInExpression(boolean in) {
		fCursorInExpression = in;
	}

	final public void setSourceCursor(int i) {
		fSourcePosition = i;
	}

	final public int getSourcePosition() {
		return fSourcePosition;
	}

	final public TLDCMDocumentManager getTLDCMDocumentManager() {
		return TaglibController.getTLDCMDocumentManager(fStructuredDocument);
	}

	final public void setRelativeOffset(int relativeOffset) {
		this.fRelativeOffset = relativeOffset;
	}

	final public int getRelativeOffset() {
		return fRelativeOffset;
	}

	private void setCursorOwner(StringBuffer cursorOwner) {
		this.fCursorOwner = cursorOwner;
	}

	final public StringBuffer getCursorOwner() {
		return fCursorOwner;
	}

	private IStructuredDocumentRegion setCurrentNode(IStructuredDocumentRegion currentNode) {
		return this.fCurrentNode = currentNode;
	}

	final public IStructuredDocumentRegion getCurrentNode() {
		return fCurrentNode;
	}

	public IStructuredDocument getStructuredDocument() {
		return fStructuredDocument;
	}

	private IPath getModelPath() {
		IPath path = null;
		ITextFileBuffer buffer = FileBufferModelManager.getInstance().getBuffer(getStructuredDocument());
		if (buffer != null) {
			path = buffer.getLocation();
		}
		return path;
	}

	private void translateCodas() {
		fProcessIncludes = false;
		IPath modelpath = getModelPath();
		if (modelpath != null) {
			PropertyGroup[] propertyGroups = DeploymentDescriptorPropertyCache.getInstance().getPropertyGroups(modelpath);
			for (int j = 0; j < propertyGroups.length; j++) {
				IPath[] codas = propertyGroups[j].getIncludeCoda();
				for (int i = 0; i < codas.length; i++) {
					if (!getIncludes().contains(codas[i].toString()) && !codas[i].equals(modelpath)) {
						getIncludes().push(codas[i]);
						JSPIncludeRegionHelper helper = new JSPIncludeRegionHelper(this, true);
						helper.parse(codas[i].toString());
						getIncludes().pop();
					}
				}
			}
		}
		fProcessIncludes = true;
	}

	private void translatePreludes() {
		fProcessIncludes = false;
		IPath modelpath = getModelPath();
		if (modelpath != null) {
			PropertyGroup[] propertyGroups = DeploymentDescriptorPropertyCache.getInstance().getPropertyGroups(modelpath);
			for (int j = 0; j < propertyGroups.length; j++) {
				IPath[] preludes = propertyGroups[j].getIncludePrelude();
				for (int i = 0; i < preludes.length; i++) {
					if (!getIncludes().contains(preludes[i].toString()) && !preludes[i].equals(modelpath)) {
						getIncludes().push(preludes[i]);
						JSPIncludeRegionHelper helper = new JSPIncludeRegionHelper(this, true);
						helper.parse(preludes[i].toString());
						getIncludes().pop();
					}
				}
			}
		}
		fProcessIncludes = true;
	}

	/**
	 * <p>Writes an empty expression to {@link #fUserCode} if previously
	 * found non translated code</p>
	 * <p>This should be done before appending any newly translated code.</p>
	 */
	private void writePlaceHolderForNonTranslatedCode() {
		if(fFoundNonTranslatedCode) {
			String text = ("{" + EXPRESSION_PREFIX + "\"\"" + EXPRESSION_SUFFIX + "}" + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
					" //markup"+ ENDL); //$NON-NLS-1$
			fUserCode.append(text);
			fOffsetInUserCode += text.length();
			fFoundNonTranslatedCode = false;
		}
	}

	/**
	 * <p><b>NOTE: </b>If the implementation of this method is changed be sure to update
	 *  {@link #readExternal(ObjectInput)} and {@link #serialVersionUID}</p>
	 *
	 * @see #readExternal(ObjectInput)
	 * @see #serialVersionUID
	 * @see java.io.Externalizable#writeExternal(java.io.ObjectOutput)
	 */
	public void writeExternal(ObjectOutput out) throws IOException {
		writeString(out, this.fClassHeader);
		writeString(out, this.fClassname);
		writeString(out, this.fSuperclass);
		writeString(out, this.fImplicitImports);
		writeString(out, this.fServiceHeader);
		writeBuffer(out, this.fUserImports);
		out.writeInt(this.fSourcePosition);
		out.writeInt(this.fRelativeOffset);
		out.writeInt(this.fCursorPosition);
		out.writeBoolean(this.fIsErrorPage);
		out.writeBoolean(this.fCursorInExpression);
		out.writeBoolean(this.fIsInASession);
		writeBuffer(out, this.fUserCode);
		writeBuffer(out, this.fUserELExpressions);
		writeBuffer(out, this.fUserDeclarations);
		writeBuffer(out, this.fCursorOwner);
		out.writeBoolean(this.fInCodeRegion);
		out.writeBoolean(this.fProcessIncludes);
		out.writeInt(this.fOffsetInUserImports);
		out.writeInt(this.fOffsetInUserDeclarations);
		out.writeInt(this.fOffsetInUserCode);
		
		//write included paths
		out.writeInt(this.fIncludedPaths.size());
		Iterator iter = this.fIncludedPaths.iterator();
		while(iter.hasNext()) {
			writeString(out, (String)iter.next());
		}
		
		writeRanges(out, this.fImportRanges);
		writeRanges(out, this.fCodeRanges);
		writeRanges(out, this.fDeclarationRanges);
		writeRanges(out, this.fUseBeanRanges);
		writeRanges(out, this.fUserELRanges);
		writeRanges(out, this.fIndirectRanges);
		writeString(out, this.fELTranslatorID);
	}
	
	/**
	 * <p><b>NOTE 1: </b>After reading in an externalized {@link JSPTranslator} the caller must
	 * manually call {@link #postReadExternalSetup(IStructuredModel)} to finish setting up
	 * the {@link JSPTranslator} for use.</p>
	 * 
	 * <p><b>NOTE 2: </b>If the implementation of this method is changed be sure to update
	 * {@link #writeExternal(ObjectOutput)} and {@link #serialVersionUID}</p>
	 * 
	 * @see #writeExternal(ObjectOutput)
	 * @see #serialVersionUID
	 * @see java.io.Externalizable#readExternal(java.io.ObjectInput)
	 */
	public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
		this.fClassHeader = readString(in);
		this.fClassname = readString(in);
		this.fSuperclass = readString(in);
		this.fImplicitImports = readString(in);
		this.fServiceHeader = readString(in);
		this.fUserImports = new StringBuffer(readString(in));
		this.fSourcePosition = in.readInt();
		this.fRelativeOffset = in.readInt();
		this.fCursorPosition = in.readInt();
		this.fIsErrorPage = in.readBoolean();
		this.fCursorInExpression = in.readBoolean();
		this.fIsInASession = in.readBoolean();
		this.fUserCode = new StringBuffer(readString(in));
		this.fUserELExpressions = new StringBuffer(readString(in));
		this.fUserDeclarations = new StringBuffer(readString(in));
		this.fCursorOwner = new StringBuffer(readString(in));
		this.fInCodeRegion = in.readBoolean();
		this.fProcessIncludes = in.readBoolean();
		this.fOffsetInUserImports = in.readInt();
		this.fOffsetInUserDeclarations = in.readInt();
		this.fOffsetInUserCode = in.readInt();
		
		//read included paths
		int size = in.readInt();
		this.fIncludedPaths = new HashSet(size);
		for(int i = 0; i < size; ++i) {
			this.fIncludedPaths.add(readString(in));
		}
		
		this.fImportRanges = readRanges(in);
		this.fCodeRanges = readRanges(in);
		this.fDeclarationRanges = readRanges(in);
		this.fUseBeanRanges = readRanges(in);
		this.fUserELRanges = readRanges(in);
		this.fIndirectRanges = readRanges(in);
		this.fELTranslatorID = readString(in);
		
		//build result
		this.buildResult(false);
	}
	
	/**
	 * <p>This does mandatory setup needed after a JSPTranslator is restored from
	 * a persisted file</p>
	 * 
	 * @param jspModel {@link IStructuredModel} representing the JSP file that this
	 * is a translator for
	 */
	protected void postReadExternalSetup(IStructuredModel jspModel) {
		this.fStructuredDocument = jspModel.getStructuredDocument();
		this.fJspTextBuffer = new StringBuffer(this.fStructuredDocument.get());
		if(jspModel instanceof IDOMModel) {
			this.fStructuredModel = (IDOMModel)jspModel;
		}
	}
	
	/**
	 * <p>Writes a string to an {@link ObjectOutput} stream</p>
	 * 
	 * <p><b>NOTE: </b>If the implementation of this method is changed be sure to update
	 * {@link #readString(ObjectInput)} and {@link #serialVersionUID}</p>
	 * 
	 * @param out {@link ObjectOutput} stream to write <code>s</code> too
	 * @param s {@link String} to write to <code>out</code>
	 * 
	 * @throws IOException IO can throw exceptions
	 * 
	 * @see #readString(ObjectInput)
	 */
	private static void writeString(ObjectOutput out, String s) throws IOException {
		if(s != null) {
			out.writeInt(s.length());
			out.writeBytes(s);
		} else {
			out.writeInt(0);
		}
	}
	
	/**
	 * <p>Reads a {@link String} written by {@link #writeString(ObjectOutput, String)} from
	 * a {@link ObjectInput} stream.</p>
	 * 
	 * <p><b>NOTE: </b>If the implementation of this method is changed be sure to update
	 * {@link #writeString(ObjectOutput, String)} and {@link #serialVersionUID}</p>
	 * 
	 * @param in {@link ObjectInput} stream to read the {@link String} from
	 * @return {@link String} read from <code>in</code>
	 * 
	 * @throws IOException IO Can throw exceptions
	 * 
	 * @see #writeString(ObjectOutput, String)
	 */
	private static String readString(ObjectInput in) throws IOException {
		int length = in.readInt();
		byte[] bytes = new byte[length];
		in.readFully(bytes);
		return new String(bytes);
	}
	
	/**
	 * <p>Writes a {@link StringBuffer} to an {@link ObjectOutput} stream</p>
	 * 
	 * @param out {@link ObjectOutput} stream to write <code>s</code> too
	 * @param s {@link String} to write to <code>out</code>
	 * 
	 * @throws IOException IO can throw exceptions
	 * 
	 * @see #readString(ObjectInput)
	 */
	private static void writeBuffer(ObjectOutput out, StringBuffer buff) throws IOException {
		if(buff != null && buff.length() > 0) {
			writeString(out, buff.toString());
		} else {
			writeString(out, null);
		}
	}
	
	/**
	 * <p>Writes a {@link HashMap} of {@link Position}s to an {@link ObjectOutput} stream</p>
	 * 
	 * <p><b>NOTE: </b>If the implementation of this method is changed be sure to update
	 * {@link #readRanges(ObjectInput)} and {@link #serialVersionUID}</p>
	 * 
	 * @param out {@link ObjectOutput} stream to write to
	 * @param ranges {@link HashMap} of {@link Position}s to write to <code>out</code>
	 * 
	 * @throws IOException IO can throw exceptions
	 * 
	 * @see #readRanges(ObjectInput)
	 */
	private static void writeRanges(ObjectOutput out, HashMap ranges) throws IOException {
		//this is a strange hack because Position is not designed to be used as keys in a Map, see Position doc
		HashMap temp = new HashMap();
		temp.putAll(ranges);
		
		Iterator iter = temp.keySet().iterator();
		out.writeInt(ranges.size());
		while(iter.hasNext()) {
			Position javaPos = (Position)iter.next();
			Position jspPos = (Position)temp.get(javaPos);
			out.writeInt(javaPos.offset);
			out.writeInt(javaPos.length);
			out.writeBoolean(javaPos.isDeleted);
			
			if(jspPos != null) {
				out.writeInt(jspPos.offset);
				out.writeInt(jspPos.length);
				out.writeBoolean(jspPos.isDeleted);
			} else {
				out.writeInt(-1);
				out.writeInt(-1);
			}
		}
	}
	
	/**
	 * <p>Reads a {@link HashMap} of {@link Position}s from an {@link ObjectInput} stream that was written by
	 * {@link #writeRanges(ObjectOutput, HashMap)}</p>
	 * 
	 * <p><b>NOTE: </b>If the implementation of this method is changed be sure to update
	 * {@link #writeRanges(ObjectOutput, HashMap)} and {@link #serialVersionUID}</p>
	 * 
	 * @param in {@link ObjectInput} stream to read the {@link HashMap} of {@link Position}s from
	 * @return {@link HashMap} of {@link Position}s read from <code>in</code>
	 * 
	 * @throws IOException IO can throw exceptions
	 * 
	 * @see #writeRanges(ObjectOutput, HashMap)
	 */
	private static HashMap readRanges(ObjectInput in) throws IOException {
		int size = in.readInt();
		HashMap ranges = new HashMap(size);
		for(int i = 0; i < size; ++i) {
			Position javaPos = new Position(in.readInt(), in.readInt());
			if(in.readBoolean()) {
				javaPos.delete();
			}
			
			//if the jspPos was null for some reason then -1 was written for length and offset
			Position jspPos = null;
			int jspPosOffset = in.readInt();
			int jspPosLength = in.readInt();
			if(jspPosOffset != -1 && jspPosLength != -1) {
				jspPos = new Position(jspPosOffset, jspPosLength);
			}
			
			//only read a boolean if the jspPos was not null
			if(jspPos != null && in.readBoolean()) {
				jspPos.delete();
			}
			
			ranges.put(javaPos, jspPos);
		}
		
		return ranges;
	}
	
	/**
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	public boolean equals(Object obj) {
		boolean equal = false;
		if(obj instanceof JSPTranslator) {
			JSPTranslator other = (JSPTranslator)obj;
			equal = this.fClassHeader.equals(other.fClassHeader) &&
				this.fClassname.equals(other.fClassname) &&
				this.fSuperclass.equals(other.fSuperclass) &&
				this.fImplicitImports.equals(other.fImplicitImports) &&
				this.fServiceHeader.equals(other.fServiceHeader) &&
				buffersEqual(this.fUserImports, other.fUserImports) &&
				this.fSourcePosition == other.fSourcePosition &&
				this.fRelativeOffset == other.fRelativeOffset &&
				this.fCursorPosition == other.fCursorPosition &&
				this.fIsErrorPage == other.fIsErrorPage &&
				this.fCursorInExpression == other.fCursorInExpression &&
				this.fIsInASession == other.fIsInASession &&
				buffersEqual(this.fUserCode, other.fUserCode) &&
				buffersEqual(this.fUserELExpressions, other.fUserELExpressions) &&
				buffersEqual(this.fUserDeclarations, other.fUserDeclarations) &&
				buffersEqual(this.fCursorOwner, other.fCursorOwner) &&
				this.fInCodeRegion == other.fInCodeRegion &&
				this.fProcessIncludes == other.fProcessIncludes &&
				this.fOffsetInUserImports == other.fOffsetInUserImports &&
				this.fOffsetInUserDeclarations == other.fOffsetInUserDeclarations &&
				this.fOffsetInUserCode == other.fOffsetInUserCode &&
				rangesEqual(this.fImportRanges, other.fImportRanges) &&
				rangesEqual(this.fCodeRanges, other.fCodeRanges) &&
				rangesEqual(this.fDeclarationRanges, other.fDeclarationRanges) &&
				rangesEqual(this.fUseBeanRanges, other.fUseBeanRanges) &&
				rangesEqual(this.fUserELRanges, other.fUserELRanges) &&
				rangesEqual(this.fIndirectRanges, other.fIndirectRanges) &&
				(
					(this.fELTranslatorID != null && other.fELTranslatorID != null) ||
					(this.fELTranslatorID == null && other.fELTranslatorID != null && other.fELTranslatorID.length() == 0) ||
					(this.fELTranslatorID != null && this.fELTranslatorID.length() == 0 && other.fELTranslatorID == null) ||
					(this.fELTranslatorID.equals(other.fELTranslator))
				);
		}
		return equal;
	}
	
	/**
	 * <p><code>null</code> is considered equivlent to an empty buffer</p>
	 * 
	 * @param buff1 can be <code>null</code>
	 * @param buff2 can be <code>null</code>
	 * @return <code>true</code> if the two given buffers are equal, <codee>false</code> otherwise
	 */
	private static boolean buffersEqual(StringBuffer buff1, StringBuffer buff2) {
		return (buff1 == null && buff2 == null) ||
			(buff1 != null && buff2!= null && buff1.toString().equals(buff2.toString())) ||
			(buff1 == null && buff2 != null && buff2.length() == 0) ||
			(buff1 != null && buff1.length() == 0 && buff2 == null);
	}
	
	/**
	 * @param ranges1
	 * @param ranges2
	 * @return <code>true</code> if the two maps of ranges contains the same key/value pares,
	 * <code>false</code> otherwise
	 */
	private static boolean rangesEqual(HashMap ranges1, HashMap ranges2) {
		//this is a strange hack because Position is not designed to be used as keys in a Map, see Position doc
		HashMap temp = new HashMap();
		temp.putAll(ranges1);
		ranges1 = temp;
		
		boolean equal = false;
		if(ranges1 != null && ranges2 != null) {
			equal = true;
			Iterator ranges1Keys = ranges1.keySet().iterator();
			while(ranges1Keys.hasNext() && equal) {
				Position key = (Position)ranges1Keys.next();
				Position ranges1Value = (Position)ranges1.get(key);
				Position ranges2Value = (Position)ranges2.get(key);
				equal = ranges1Value.equals(ranges2Value);
			}
		}
		
		return equal;
	}
}
